1.Java 集合中 List 和 Set区别是什么?
| 特性 | List (有序集合) | Set (无序集合) |
|---|---|---|
| 重复性 | 允许重复元素。 | 不允许重复元素。 |
| 有序性 | 有序。维护元素的插入顺序。 | 无序(一般情况下)。不保证维护插入顺序。 |
| 索引访问 | 支持。可以通过索引精确控制插入位置并访问元素。 | 不支持。不能通过索引获取元素。 |
| 底层实现 | 动态数组(ArrayList)或双向链表(LinkedList)。 | 哈希表(HashSet)或红黑树(TreeSet)。 |
“简单来说,如果你需要存储一组允许重复且需要严格记录先后顺序的数据,首选 List(如 ArrayList);如果你需要自动去重且不关心顺序,首选 Set(如 HashSet)。在特殊场景下,如果既要取重又要排序,则使用 TreeSet。” |
2.如何对Set排序?
| 方案 | 排序时机 | 底层实现 | 排序规则 |
|---|---|---|---|
TreeSet | 插入时自动排序 | 红黑树 | 自然顺序或自定义比较器 |
LinkedHashSet | 保持插入顺序 | 哈希表 + 双向链表 | 元素插入的先后顺序 |
List 转换法 | 手动触发排序 | 数组/链表 | 灵活,可使用 Collections.sort() |
“在实际开发中,如果数据需要始终保持有序,我会优先选择 TreeSet;如果只是偶尔需要排序输出,我会先用 HashSet 存储(保证 $O(1)$ 的查重效率),在展示前再转成 List 排序,这样能平衡性能和灵活性。” |
3.Set集合有什么特点?如何实现key无重复的?
- Set 集合的特点
-
元素唯一性:
Set不允许存储重复的元素。 -
无序性:通常情况下,
Set并不保证元素的插入顺序(HashSet表现最明显)。 -
基于 Map 实现:大多数常用的
Set实现类底层都是直接封装了对应的Map。
如何实现 Key 无重复?
以最常用的 HashSet 为例,它的去重机制完全依赖于 HashMap:
-
复用 HashMap:
HashSet内部持有一个HashMap实例。 -
作为 Key 存储:当你向
HashSet添加元素时,该元素实际上是作为底层HashMap的 Key 进行存储的。 -
统一的 Value:因为
Map需要键值对,HashSet会为所有的 Key 配上一个名为PRESENT的静态虚拟对象作为 Value。 -
利用 Map 契约:由于
HashMap的 Key 本身就是唯一的,因此HashSet天然地保证了元素的唯一性。
“Set 接口的设计其实是‘借力打力’。它的核心去重逻辑在于利用了 Map 键的唯一性。当我们向 Set 存入数据时,底层会先计算 hash 值定位桶位,再通过 equals 比较,若已存在则覆盖旧 Value(虽然 Value 对 Set 无意义),从而确保集合内没有重复对象。”
4.有序的Set是什么?记录插入顺序的集合是什么?
| 特性 | TreeSet | LinkedHashSet |
|---|---|---|
| 排序维度 | 元素值的大小 (Value Order) | 插入的先后 (Insertion Order) |
| 底层结构 | 红黑树 (TreeMap) | 哈希表 + 双向链表 |
| 查询效率 | $O(\log N)$ | $O(1)$ |
| 适用场景 | 需要对数据进行范围查询或排序输出 | 需要去重且保留用户输入顺序 |
“如果业务要求数据必须按大小排列(如成绩排行榜),我会选 TreeSet;如果业务要求数据去重但必须保留用户的操作顺序(如操作日志去重),我会选 LinkedHashSet。”