Java 集合框架深度解析:List 与 Set 的区别及体系全览
1. 引言
在 Java 开发中,集合(Collection)是最常用的工具之一。无论是存储一组对象、遍历数据,还是进行去重、排序操作,都离不开 List、Set 等集合接口。然而,很多初学者对集合的整体架构一知半解,对于 "List 是有序、可重复的;Set 是无序、不可重复的" 只停留在死记硬背,并不理解其底层原理和适用场景。
本文将带你从顶层 Collection 接口出发,全面梳理 Java 集合体系的继承关系,并深入对比 List 与 Set 的核心差异,配合 UML 类图和流程图,让你彻底搞懂:
- ✅ 集合框架的整体结构(
List、Set两大分支) - ✅
ArrayList、LinkedList、Vector的区别与选型 - ✅
HashSet、TreeSet的底层实现与排序机制 - ✅ 有序/无序 与 重复/不重复 的真正含义
- ✅ 如何根据业务场景选择合适的集合
2. 集合体系全景图(UML 类图)
Java 集合框架的根接口是 Collection,它派生出两大核心分支:List 和 Set。下面是简化的继承关系图:
#mermaid-svg-awHcBolbYXytyANS{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-awHcBolbYXytyANS .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-awHcBolbYXytyANS .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-awHcBolbYXytyANS .error-icon{fill:#552222;}#mermaid-svg-awHcBolbYXytyANS .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-awHcBolbYXytyANS .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-awHcBolbYXytyANS .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-awHcBolbYXytyANS .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-awHcBolbYXytyANS .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-awHcBolbYXytyANS .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-awHcBolbYXytyANS .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-awHcBolbYXytyANS .marker{fill:#333333;stroke:#333333;}#mermaid-svg-awHcBolbYXytyANS .marker.cross{stroke:#333333;}#mermaid-svg-awHcBolbYXytyANS svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-awHcBolbYXytyANS p{margin:0;}#mermaid-svg-awHcBolbYXytyANS g.classGroup text{fill:#9370DB;stroke:none;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:10px;}#mermaid-svg-awHcBolbYXytyANS g.classGroup text .title{font-weight:bolder;}#mermaid-svg-awHcBolbYXytyANS .cluster-label text{fill:#333;}#mermaid-svg-awHcBolbYXytyANS .cluster-label span{color:#333;}#mermaid-svg-awHcBolbYXytyANS .cluster-label span p{background-color:transparent;}#mermaid-svg-awHcBolbYXytyANS .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-awHcBolbYXytyANS .cluster text{fill:#333;}#mermaid-svg-awHcBolbYXytyANS .cluster span{color:#333;}#mermaid-svg-awHcBolbYXytyANS .nodeLabel,#mermaid-svg-awHcBolbYXytyANS .edgeLabel{color:#131300;}#mermaid-svg-awHcBolbYXytyANS .edgeLabel .label rect{fill:#ECECFF;}#mermaid-svg-awHcBolbYXytyANS .label text{fill:#131300;}#mermaid-svg-awHcBolbYXytyANS .labelBkg{background:#ECECFF;}#mermaid-svg-awHcBolbYXytyANS .edgeLabel .label span{background:#ECECFF;}#mermaid-svg-awHcBolbYXytyANS .classTitle{font-weight:bolder;}#mermaid-svg-awHcBolbYXytyANS .node rect,#mermaid-svg-awHcBolbYXytyANS .node circle,#mermaid-svg-awHcBolbYXytyANS .node ellipse,#mermaid-svg-awHcBolbYXytyANS .node polygon,#mermaid-svg-awHcBolbYXytyANS .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-awHcBolbYXytyANS .divider{stroke:#9370DB;stroke-width:1;}#mermaid-svg-awHcBolbYXytyANS g.clickable{cursor:pointer;}#mermaid-svg-awHcBolbYXytyANS g.classGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-awHcBolbYXytyANS g.classGroup line{stroke:#9370DB;stroke-width:1;}#mermaid-svg-awHcBolbYXytyANS .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-awHcBolbYXytyANS .classLabel .label{fill:#9370DB;font-size:10px;}#mermaid-svg-awHcBolbYXytyANS .relation{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-awHcBolbYXytyANS .dashed-line{stroke-dasharray:3;}#mermaid-svg-awHcBolbYXytyANS .dotted-line{stroke-dasharray:1 2;}#mermaid-svg-awHcBolbYXytyANS #compositionStart,#mermaid-svg-awHcBolbYXytyANS .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-awHcBolbYXytyANS #compositionEnd,#mermaid-svg-awHcBolbYXytyANS .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-awHcBolbYXytyANS #dependencyStart,#mermaid-svg-awHcBolbYXytyANS .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-awHcBolbYXytyANS #dependencyStart,#mermaid-svg-awHcBolbYXytyANS .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-awHcBolbYXytyANS #extensionStart,#mermaid-svg-awHcBolbYXytyANS .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-awHcBolbYXytyANS #extensionEnd,#mermaid-svg-awHcBolbYXytyANS .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-awHcBolbYXytyANS #aggregationStart,#mermaid-svg-awHcBolbYXytyANS .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-awHcBolbYXytyANS #aggregationEnd,#mermaid-svg-awHcBolbYXytyANS .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-awHcBolbYXytyANS #lollipopStart,#mermaid-svg-awHcBolbYXytyANS .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-awHcBolbYXytyANS #lollipopEnd,#mermaid-svg-awHcBolbYXytyANS .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-awHcBolbYXytyANS .edgeTerminals{font-size:11px;line-height:initial;}#mermaid-svg-awHcBolbYXytyANS .classTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-awHcBolbYXytyANS .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-awHcBolbYXytyANS .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-awHcBolbYXytyANS :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} <<interface>>
Collection
+add()
+remove()
+size()
+iterator()
<<interface>>
List
+get(index)
+set(index, element)
+indexOf()
+subList()
<<interface>>
Set
ArrayList
+底层数组
+随机访问快
+增删慢(末尾除外)
LinkedList
+底层双向链表
+增删快
+随机访问慢
Vector
+线程安全
+性能较差
HashSet
+底层HashMap
+无序
+允许null
TreeSet
+底层TreeMap
+自动排序
+不允许null(默认)
LinkedHashSet
+底层LinkedHashMap
+按插入顺序迭代
说明:
List接口:有序、可重复、有索引。Set接口:无序(或特定顺序)、不可重复、无索引。- 虚线箭头表示实现接口,实线箭头表示继承。
3. List:有序可重复的序列
List 代表一个有序集合(Ordered Collection),即元素按照插入顺序排列,并且可以包含重复元素。每个元素都有一个整数索引,可以精确访问。
3.1 List 的核心特性
| 特性 | 描述 |
|---|---|
| 有序性 | 迭代顺序 = 插入顺序(除非手动排序)。 |
| 可重复性 | 允许存储 e1.equals(e2) == true 的元素。 |
| 索引访问 | 提供 get(int index)、set(int index, E element) 等方法。 |
| 遍历方式 | for 循环、增强 for、Iterator、ListIterator。 |
3.2 常用实现类对比
| 实现类 | 底层数据结构 | 随机访问 | 增删效率 | 线程安全 | 适用场景 |
|---|---|---|---|---|---|
ArrayList |
动态数组 | O(1) | 尾部 O(1),中间 O(n) | 否 | 查询多、增删少 |
LinkedList |
双向链表 | O(n) | 头部/尾部 O(1),中间 O(n) | 否 | 频繁头尾增删 |
Vector |
动态数组(同步) | O(1) | 尾部 O(1),中间 O(n) | 是(但落后) | 已过时,不建议使用 |
示例:
java
List<String> arrayList = new ArrayList<>();
arrayList.add("A"); // 尾部插入
arrayList.add(0, "B"); // 中间插入,元素后移
List<String> linkedList = new LinkedList<>();
linkedList.addFirst("head");
linkedList.addLast("tail");
💡 选型建议:
- 大多数场景用
ArrayList,因为实际查询需求远多于中间插入。- 如果需要线程安全的
List,使用Collections.synchronizedList()或CopyOnWriteArrayList(JUC 包)。
4. Set:不重复的集合
Set 接口代表一个不包含重复元素 的集合。数学上集合的特性------互异性------在 Java 中通过 equals() 和 hashCode() 实现。
4.1 Set 的核心特性
| 特性 | 描述 |
|---|---|
| 不可重复性 | set.add(e) 时,如果 e 已存在(根据 equals 比较),则插入失败。 |
| 无序性(部分实现) | HashSet 不保证顺序;LinkedHashSet 按插入顺序;TreeSet 按自然顺序或比较器排序。 |
| 无索引 | 无法通过下标访问,只能通过迭代器或增强 for 遍历。 |
| 常用操作 | 并集、交集、差集等集合运算。 |
4.2 常用实现类对比
| 实现类 | 底层结构 | 排序 | 允许 null | 线程安全 | 使用场景 |
|---|---|---|---|---|---|
HashSet |
HashMap |
无(哈希散列) | 一个 null | 否 | 最快去重,不关心顺序 |
LinkedHashSet |
LinkedHashMap |
插入顺序 | 一个 null | 否 | 去重并保持插入顺序 |
TreeSet |
TreeMap(红黑树) |
自然顺序/定制顺序 | 不允许 null(默认) | 否 | 需要排序去重 |
示例:
java
Set<String> hashSet = new HashSet<>();
hashSet.add("banana");
hashSet.add("apple");
hashSet.add("banana");
System.out.println(hashSet); // 无序,可能 [banana, apple]
Set<String> treeSet = new TreeSet<>();
treeSet.add("banana");
treeSet.add("apple");
System.out.println(treeSet); // [apple, banana] 按字典序
Set<String> linkedHashSet = new LinkedHashSet<>();
linkedHashSet.add("banana");
linkedHashSet.add("apple");
System.out.println(linkedHashSet); // [banana, apple] 插入顺序
⚠️ 注意:
HashSet的"无序" ≠ 随机顺序,而是指迭代顺序与插入顺序无关(依赖哈希分布)。- 自定义对象放入
HashSet/TreeSet时必须重写equals()和hashCode()(HashSet)或实现Comparable/提供Comparator(TreeSet)。
5. List vs Set:核心区别图解
#mermaid-svg-rZKmJtbqVKcYYhh6{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-rZKmJtbqVKcYYhh6 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-rZKmJtbqVKcYYhh6 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-rZKmJtbqVKcYYhh6 .error-icon{fill:#552222;}#mermaid-svg-rZKmJtbqVKcYYhh6 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-rZKmJtbqVKcYYhh6 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-rZKmJtbqVKcYYhh6 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-rZKmJtbqVKcYYhh6 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-rZKmJtbqVKcYYhh6 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-rZKmJtbqVKcYYhh6 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-rZKmJtbqVKcYYhh6 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-rZKmJtbqVKcYYhh6 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-rZKmJtbqVKcYYhh6 .marker.cross{stroke:#333333;}#mermaid-svg-rZKmJtbqVKcYYhh6 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-rZKmJtbqVKcYYhh6 p{margin:0;}#mermaid-svg-rZKmJtbqVKcYYhh6 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-rZKmJtbqVKcYYhh6 .cluster-label text{fill:#333;}#mermaid-svg-rZKmJtbqVKcYYhh6 .cluster-label span{color:#333;}#mermaid-svg-rZKmJtbqVKcYYhh6 .cluster-label span p{background-color:transparent;}#mermaid-svg-rZKmJtbqVKcYYhh6 .label text,#mermaid-svg-rZKmJtbqVKcYYhh6 span{fill:#333;color:#333;}#mermaid-svg-rZKmJtbqVKcYYhh6 .node rect,#mermaid-svg-rZKmJtbqVKcYYhh6 .node circle,#mermaid-svg-rZKmJtbqVKcYYhh6 .node ellipse,#mermaid-svg-rZKmJtbqVKcYYhh6 .node polygon,#mermaid-svg-rZKmJtbqVKcYYhh6 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-rZKmJtbqVKcYYhh6 .rough-node .label text,#mermaid-svg-rZKmJtbqVKcYYhh6 .node .label text,#mermaid-svg-rZKmJtbqVKcYYhh6 .image-shape .label,#mermaid-svg-rZKmJtbqVKcYYhh6 .icon-shape .label{text-anchor:middle;}#mermaid-svg-rZKmJtbqVKcYYhh6 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-rZKmJtbqVKcYYhh6 .rough-node .label,#mermaid-svg-rZKmJtbqVKcYYhh6 .node .label,#mermaid-svg-rZKmJtbqVKcYYhh6 .image-shape .label,#mermaid-svg-rZKmJtbqVKcYYhh6 .icon-shape .label{text-align:center;}#mermaid-svg-rZKmJtbqVKcYYhh6 .node.clickable{cursor:pointer;}#mermaid-svg-rZKmJtbqVKcYYhh6 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-rZKmJtbqVKcYYhh6 .arrowheadPath{fill:#333333;}#mermaid-svg-rZKmJtbqVKcYYhh6 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-rZKmJtbqVKcYYhh6 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-rZKmJtbqVKcYYhh6 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-rZKmJtbqVKcYYhh6 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-rZKmJtbqVKcYYhh6 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-rZKmJtbqVKcYYhh6 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-rZKmJtbqVKcYYhh6 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-rZKmJtbqVKcYYhh6 .cluster text{fill:#333;}#mermaid-svg-rZKmJtbqVKcYYhh6 .cluster span{color:#333;}#mermaid-svg-rZKmJtbqVKcYYhh6 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-rZKmJtbqVKcYYhh6 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-rZKmJtbqVKcYYhh6 rect.text{fill:none;stroke-width:0;}#mermaid-svg-rZKmJtbqVKcYYhh6 .icon-shape,#mermaid-svg-rZKmJtbqVKcYYhh6 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-rZKmJtbqVKcYYhh6 .icon-shape p,#mermaid-svg-rZKmJtbqVKcYYhh6 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-rZKmJtbqVKcYYhh6 .icon-shape .label rect,#mermaid-svg-rZKmJtbqVKcYYhh6 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-rZKmJtbqVKcYYhh6 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-rZKmJtbqVKcYYhh6 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-rZKmJtbqVKcYYhh6 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Set特点
不可重复
元素唯一
无索引
不能按位置访问
部分有序
TreeSet/LinkedHashSet提供特定顺序
List特点
有序
按插入顺序迭代
可重复
允许重复元素
有索引
get/set by index
5.1 对比表格
| 维度 | List | Set |
|---|---|---|
| 顺序 | 保证插入顺序 | 一般无序(除 LinkedHashSet、TreeSet) |
| 重复 | 允许重复 | 不允许重复 |
| 索引 | 有索引(通过整数访问) | 无索引,只能通过迭代器或增强 for |
| 常用实现 | ArrayList, LinkedList, Vector |
HashSet, LinkedHashSet, TreeSet |
| 典型场景 | 需要保持顺序、可能需要重复、根据位置访问 | 去重、集合运算、自动排序 |
| 性能(查找) | 随机访问 O(1)(数组),链表 O(n) | HashSet O(1),TreeSet O(log n) |
| 允许 null | 允许任意多个 null | 最多一个 null(TreeSet 不允许) |
5.2 代码对比示例
java
// List 可以重复
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(1);
System.out.println(list.size()); // 2
// Set 自动去重
Set<Integer> set = new HashSet<>();
set.add(1);
set.add(1);
System.out.println(set.size()); // 1
6. 如何选择 List 还是 Set?
#mermaid-svg-SB1PN9ulYftdxcat{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-SB1PN9ulYftdxcat .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-SB1PN9ulYftdxcat .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-SB1PN9ulYftdxcat .error-icon{fill:#552222;}#mermaid-svg-SB1PN9ulYftdxcat .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-SB1PN9ulYftdxcat .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-SB1PN9ulYftdxcat .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-SB1PN9ulYftdxcat .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-SB1PN9ulYftdxcat .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-SB1PN9ulYftdxcat .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-SB1PN9ulYftdxcat .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-SB1PN9ulYftdxcat .marker{fill:#333333;stroke:#333333;}#mermaid-svg-SB1PN9ulYftdxcat .marker.cross{stroke:#333333;}#mermaid-svg-SB1PN9ulYftdxcat svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-SB1PN9ulYftdxcat p{margin:0;}#mermaid-svg-SB1PN9ulYftdxcat .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-SB1PN9ulYftdxcat .cluster-label text{fill:#333;}#mermaid-svg-SB1PN9ulYftdxcat .cluster-label span{color:#333;}#mermaid-svg-SB1PN9ulYftdxcat .cluster-label span p{background-color:transparent;}#mermaid-svg-SB1PN9ulYftdxcat .label text,#mermaid-svg-SB1PN9ulYftdxcat span{fill:#333;color:#333;}#mermaid-svg-SB1PN9ulYftdxcat .node rect,#mermaid-svg-SB1PN9ulYftdxcat .node circle,#mermaid-svg-SB1PN9ulYftdxcat .node ellipse,#mermaid-svg-SB1PN9ulYftdxcat .node polygon,#mermaid-svg-SB1PN9ulYftdxcat .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-SB1PN9ulYftdxcat .rough-node .label text,#mermaid-svg-SB1PN9ulYftdxcat .node .label text,#mermaid-svg-SB1PN9ulYftdxcat .image-shape .label,#mermaid-svg-SB1PN9ulYftdxcat .icon-shape .label{text-anchor:middle;}#mermaid-svg-SB1PN9ulYftdxcat .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-SB1PN9ulYftdxcat .rough-node .label,#mermaid-svg-SB1PN9ulYftdxcat .node .label,#mermaid-svg-SB1PN9ulYftdxcat .image-shape .label,#mermaid-svg-SB1PN9ulYftdxcat .icon-shape .label{text-align:center;}#mermaid-svg-SB1PN9ulYftdxcat .node.clickable{cursor:pointer;}#mermaid-svg-SB1PN9ulYftdxcat .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-SB1PN9ulYftdxcat .arrowheadPath{fill:#333333;}#mermaid-svg-SB1PN9ulYftdxcat .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-SB1PN9ulYftdxcat .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-SB1PN9ulYftdxcat .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-SB1PN9ulYftdxcat .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-SB1PN9ulYftdxcat .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-SB1PN9ulYftdxcat .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-SB1PN9ulYftdxcat .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-SB1PN9ulYftdxcat .cluster text{fill:#333;}#mermaid-svg-SB1PN9ulYftdxcat .cluster span{color:#333;}#mermaid-svg-SB1PN9ulYftdxcat div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-SB1PN9ulYftdxcat .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-SB1PN9ulYftdxcat rect.text{fill:none;stroke-width:0;}#mermaid-svg-SB1PN9ulYftdxcat .icon-shape,#mermaid-svg-SB1PN9ulYftdxcat .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-SB1PN9ulYftdxcat .icon-shape p,#mermaid-svg-SB1PN9ulYftdxcat .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-SB1PN9ulYftdxcat .icon-shape .label rect,#mermaid-svg-SB1PN9ulYftdxcat .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-SB1PN9ulYftdxcat .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-SB1PN9ulYftdxcat .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-SB1PN9ulYftdxcat :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 允许重复
不允许重复
随机访问多
头尾增删多
需要自然顺序或定制顺序
需要保持插入顺序
只要求去重,对顺序无要求
需要存储一组元素
元素是否允许重复?
选择 List
选择 Set
操作主要是随机访问还是频繁增删?
ArrayList
LinkedList
是否需要排序?
TreeSet
LinkedHashSet
HashSet
决策要点:
- 如果元素必须按某个特定顺序(如用户操作日志),用
List。 - 如果业务要求元素唯一(如用户ID集合),用
Set。 - 如果既需要去重又需要保持插入顺序,用
LinkedHashSet。 - 如果既需要去重又需要自动排序,用
TreeSet。
7. 常见面试题
Q1: 为什么 HashSet 不保证顺序,而 LinkedHashSet 可以?
因为 HashSet 底层使用 HashMap,元素的存储位置由哈希码决定,插入顺序无法保留。LinkedHashSet 在 HashMap 基础上额外维护了一个双向链表,记录了插入顺序,因此迭代时按插入顺序输出。
Q2: ArrayList 和 LinkedList 谁的内存占用更大?
LinkedList 每个节点需要存储前驱和后继引用,额外内存开销比 ArrayList 大。ArrayList 底层数组会有一定的容量预留(扩容策略),也可能存在空间浪费。总体而言,元素数量较多时 ArrayList 内存效率更高。
Q3: Vector 已经过时,为什么还在某些旧项目中出现?
Vector 是 JDK 1.0 就存在的线程安全 List,方法使用 synchronized 修饰,性能较差。Java 1.2 引入 ArrayList 后,Vector 被标记为遗留类。如需线程安全,推荐使用 Collections.synchronizedList 或 CopyOnWriteArrayList。
Q4: 可以将 Set 转换为 List 吗?
可以,List 构造函数可以接收任何 Collection:
java
Set<String> set = new HashSet<>(Arrays.asList("A", "B"));
List<String> list = new ArrayList<>(set);
// 之后可对 list 排序、索引访问等
8. 总结
List:有序、可重复、有索引,适合需要按照插入顺序访问或根据位置操作的场景。Set:无序(或特定顺序)、不可重复、无索引,适合去重和集合运算。- 选择集合时,优先考虑元素是否唯一、顺序要求、访问模式。
- 熟悉底层数据结构(数组、链表、哈希表、红黑树)有助于理解性能差异。
记忆口诀:
List 排队可重复,Set 唯一不重复。
索引增删看实现,Hash 最快 Tree 排序。