登录
首页 >  文章 >  java教程

JavaSet接口实现及去重技巧解析

时间:2026-02-03 16:00:55 250浏览 收藏

珍惜时间,勤奋学习!今天给大家带来《Java Set接口常用实现及去重方法解析》,正文内容主要涉及到等等,如果你正在学习文章,或者是对文章有疑问,欢迎大家关注我!后面我会持续更新相关内容的,希望都能帮到正在学习的大家!

HashSet 是去重首选,O(1) 时间复杂度,不保证顺序,依赖 hashCode() 和 equals(),允许一个 null,线程不安全;LinkedHashSet 保持插入顺序,开销略高;TreeSet 支持排序,O(log n),基于红黑树;Stream.distinct() 底层用 LinkedHashSet,语法糖。

在Java里Set接口有哪些常用实现_Java集合去重方案说明

HashSet 是去重最常用的选择,但不保证顺序

绝大多数场景下,HashSet 是首选:插入、查找、删除平均时间复杂度都是 O(1),底层基于 HashMap 实现,只存 key,value 固定为 Presentation(Java 8+ 是 PRESENT 这个静态对象)。它依赖元素的 hashCode()equals() 判断重复。

  • 必须确保自定义类正确重写 hashCode()equals(),否则去重失效
  • 不维护插入顺序,遍历时顺序不可预测
  • 允许一个 null 元素
  • 线程不安全,多线程写入需额外同步(如用 Collections.synchronizedSet()ConcurrentHashMap.newKeySet()

LinkedHashSet 保留插入顺序,开销略高

当需要去重同时保持「第一次出现的顺序」时,LinkedHashSet 是直接替代方案。它继承自 HashSet,内部用双向链表维护插入顺序,所以迭代顺序 = 插入顺序。

  • 时间复杂度和 HashSet 相同(O(1) 平均),但常数更大(要维护链表指针)
  • 内存占用略高(每个节点多两个引用)
  • 同样要求正确实现 hashCode()equals()
  • 也只允许一个 null

TreeSet 适合需要排序的去重场景

如果去重后还希望元素天然有序(升序),且能接受 O(log n) 的操作代价,TreeSet 是合适选择。它基于红黑树,支持自然排序或自定义 Comparator

  • 元素必须可比较:要么实现 Comparable,要么构造时传入 Comparator
  • null 值在无 Comparator 时会抛 NullPointerException;有 Comparator 且明确处理 null 才可存
  • 去重逻辑基于 compareTo()compare() 返回 0,而非 equals() —— 这点容易踩坑:若比较逻辑和 equals() 不一致,行为可能违反集合契约

Stream.distinct() 是函数式去重语法糖,底层仍是 HashSet

Java 8+ 中常用 stream().distinct() 做链式去重,例如:

List<String> unique = list.stream().distinct().collect(Collectors.toList());

它本质是用 LinkedHashSet 缓存已见元素(保证顺序),所以等价于手动 new 一个 LinkedHashSet 再转回 List。注意:

  • 对基本类型包装类(Integer, String)没问题;自定义对象仍需 hashCode()/equals()
  • 不能传入自定义比较器 —— 如需按某字段去重,得用 collectingAndThen + toMap 等组合方案
  • 性能略低于直接操作 HashSet,因涉及 Stream 管道开销
实际选型时,别只看「去重」二字。是否要顺序?是否要排序?是否并发写入?元素是否天然可比?这些条件比「Set 有哪几个实现」更决定该用哪一个。

理论要掌握,实操不能落!以上关于《JavaSet接口实现及去重技巧解析》的详细介绍,大家都掌握了吧!如果想要继续提升自己的能力,那么就来关注golang学习网公众号吧!

前往漫画官网入口并下载 ➜
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>