一文了解 Java 集合框架:List、Set、Map 谁该选?

Java 集合框架是开发中最常用也最容易误用的部分。List、Set、Map 看似简单,其实背后有不少值得推敲的选择逻辑。今天我们从底层实现、使用语义、性能差异三个维度全面解析。


一、Java 集合框架总览

Java 的集合大致分为两大类:

  • Collection 接口族(单值集合):如 List、Set、Queue。

  • Map 接口族(键值对集合):如 HashMap、TreeMap。

它们均继承自 java.util 包中的核心接口,并基于不同的数据结构实现。


二、List:有序可重复的序列集合

常见实现:

实现类

底层结构

适用场景

ArrayList

数组

随机访问频繁、插入较少

LinkedList

双向链表

插入删除频繁、迭代为主

CopyOnWriteArrayList

数组 + 写时复制

并发读多写少场景

特性:

  • 元素按插入顺序排列;

  • 允许重复值;

  • 可通过索引访问元素。


三、Set:去重 + 无序(或有序)的集合

常见实现:

实现类

底层结构

特点

HashSet

HashMap 支持

插入快,无序,基于哈希去重

LinkedHashSet

HashMap + 链表

保证插入顺序

TreeSet

红黑树(TreeMap)

自动排序,元素需实现 Comparable

特性:

  • 不允许重复元素;

  • 默认无序,可通过 TreeSet 实现排序。


四、Map:键值对集合,快速映射查找

常见实现:

实现类

底层结构

特点

HashMap

数组 + 链表/红黑树

查找快,键不可重复,线程不安全

LinkedHashMap

HashMap + 双向链表

保留插入顺序

TreeMap

红黑树

自动按 key 排序,适合区间查找

ConcurrentHashMap

分段锁 / CAS

并发环境推荐,线程安全

特性:

  • 每个 key 唯一,value 可重复;

  • 可通过 key 快速定位 value;

  • TreeMap 可用于范围查询与有序 key 管理。


五、如何选?典型使用场景对比

需求场景

推荐集合

说明

快速索引,允许重复

List(ArrayList)

下标访问 O(1),插入删除 O(n)

去重 + 无序存储

HashSet

内部用 HashMap 实现

保持插入顺序 + 去重

LinkedHashSet

内部维护双向链表

自动排序 + 无重复

TreeSet

内部红黑树,有序输出

键值存储,查找频繁

HashMap

key 必须实现 hashCode 与 equals

保持插入顺序的键值映射

LinkedHashMap

可用于构建 LRU 缓存

线程安全键值对存储

ConcurrentHashMap

高并发推荐,读写分离提升性能


六、List vs Set vs Map:底层结构对比

接口

是否有序

是否允许重复

底层数据结构

List

有序

数组 or 链表

Set

无序/有序

Hash 表 / Tree

Map

有序/无序

✅(仅 value)

Hash 表 / Tree


七、开发者常见误区

  1. 使用 List 存储去重数据 → 实际应使用 Set;

  2. 使用 HashSet 存储自定义对象却不重写 hashCode() 和 equals() → 无效去重;

  3. 使用 TreeMap 但 Key 未实现 Comparable 或未传 Comparator → 运行时异常;

  4. 在高并发场景下使用 HashMap 导致线程安全问题 → 应使用 ConcurrentHashMap。


八、各集合类源码核心方法解析

我们从最常用的三个集合类(ArrayList、HashSet、HashMap)出发,拆解其底层源码实现,理解其时间复杂度、扩容机制与数据结构本质。

🔹ArrayList 核心源码解析

public boolean add(E e) {
    ensureCapacityInternal(size + 1);  // 自动扩容
    elementData[size++] = e;
    return true;
}

  1. 底层结构:动态数组 Object[] elementData;

  2. 扩容机制:容量不够时扩展为 oldCapacity + (oldCapacity >> 1)(即 1.5 倍);

  3. 时间复杂度

  • 随机访问:O(1)

  • 插入末尾:O(1) 均摊

  • 插入中间:O(n)


🔹HashSet 核心源码解析(基于 HashMap)

public boolean add(E e) {
    return map.put(e, PRESENT) == null;
}
  1. 底层结构:使用 HashMap<E, Object> 实现;

  2. 唯一性保障:依赖 key 的 hashCode() + equals() 方法判断重复;

  3. 时间复杂度:O(1)(极端哈希冲突退化为 O(n));


🔹HashMap 核心源码解析(JDK 8+)

public V put(K key, V value) {
    return putVal(hash(key), key, value, false, true);
}

1. 核心方法:putVal() 中包含:

  • 计算 hash;

  • 根据索引定位桶位;

  • 冲突时使用链表(JDK 8+ 中链表超过阈值会转为红黑树);

2. 时间复杂度

  • 查找/插入:O(1),红黑树冲突为 O(log n)


九、集合类线程安全改造方案

在多线程场景中,Java 原生集合不是线程安全的,必须使用同步封装或并发安全类。

1. Collections.synchronizedXXX

List<String> syncList = Collections.synchronizedList(new ArrayList<>());
  • 优点:线程安全;

  • 缺点:基于 synchronized,性能一般;

  • 用于读写均衡、线程不太激烈的场景。

2. CopyOnWriteArrayList

CopyOnWriteArrayList<String> cowList = new CopyOnWriteArrayList<>();
  • 读写分离:写操作复制新数组,读操作无需加锁;

  • 缺点:写操作代价高,不适合频繁写;

  • 用于读远多于写的并发场景(如配置缓存)。

3.ConcurrentHashMap

ConcurrentHashMap<String, Object> map = new ConcurrentHashMap<>();
  • JDK 8 之后基于 CAS + 分段锁 + 红黑树;

  • 写入不阻塞读取,适合高并发读写;

  • 不支持 null key 或 value。

总结选择建议:

场景

推荐集合

低并发,简易同步

Collections.synchronizedXXX

读多写少

CopyOnWriteArrayList / CopyOnWriteArraySet

高并发读写

ConcurrentHashMap / ConcurrentSkipListMap


10、Java 21+ 新增集合特性与未来演进方向

随着 Java 的版本演进,集合框架也在不断增强功能与性能。

1. Record + 集合的简洁建模

Java 16+ 引入 record,搭配集合使用更加清晰:​​​​​​​

record User(String name, int age) {}
List<User> users = List.of(new User("Alice", 30), new User("Bob", 25));

2. Map.of(), List.of() 的不可变集合

Java 9 引入的新 API,创建只读集合:​​​​​​​

List<String> list = List.of("A", "B", "C"); // 不可修改
Map<String, Integer> map = Map.of("A", 1, "B", 2);

  • 不可变特性有助于并发编程与函数式设计;

  • 若尝试修改,会抛出 UnsupportedOperationException。

3. Java 21 的 Sequenced Collections(预览)

  • 新接口:SequencedCollection、SequencedMap;

  • 统一支持“前插、后插、正序、反序遍历”的操作;

  • 实现类如:SequencedHashMap、SequencedSet;

SequencedSet<String> set = new LinkedHashSet<>();
set.addFirst("head");
set.addLast("tail");

4. 未来演进方向(根据 JEP 与 OpenJDK 讨论)

  • 更好的不可变集合支持;

  • 集合接口层级的模块化;

  • 性能更高的并发集合类(如基于结构化并发与虚拟线程);

  • 更贴近函数式风格的操作(如 map/filter 原生支持);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小健学 Java

你的鼓励是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值