优先选 HashSet,仅当需保持插入顺序时才用 LinkedHashSet;HashSet 内存省、查询快但无序,LinkedHashSet 通过双向链表维护插入顺序,遍历稳定且性能接近 O(1)。

选 HashSet 还是 LinkedHashSet,关键看要不要“记住插入顺序”。
只去重、不关心顺序 → 用 HashSet
比如缓存用户 ID、统计访问 IP、校验重复提交等场景,只要元素不重复就行,顺序无关紧要。HashSet 底层是 HashMap,没有额外链表开销,内存更省、查询略快,是默认首选。
- 允许存一个 null
- 不保证遍历顺序,扩容后可能完全打乱
- 自定义对象必须正确重写 hashCode() 和 equals()
需要按插入顺序遍历 → 用 LinkedHashSet
比如记录操作日志、维护最近使用的资源列表、导出数据时要求顺序与输入一致等。它在 HashSet 基础上加了一条双向链表,把插入顺序稳稳记下来,遍历时直接走链表,稳定又高效。
- 遍历性能与元素个数(size)相关,不受容量(capacity)影响
- 插入/删除/查找仍是 O(1),只是常数项略高(链表指针维护成本)
- 内存占用稍大,每个节点多存两个引用(before/after)
别误用 TreeSet 替代它们
TreeSet 是按大小排序的,不是按插入顺序。如果你要的是“先加的在前”,用 TreeSet 会按字典序或自然序重排,结果往往不符合预期。它适合需要范围查询、找最大最小值、或天然需要升序展示的场景,和顺序保持无关。
不复杂但容易忽略:顺序需求一旦存在,HashSet 就不可逆——它本身不存顺序信息,后续没法补救;而 LinkedHashSet 多出来的开销,在绝大多数业务规模下几乎感知不到。


















