好的,我理解了你的要求。以后在回答这类体系化的问题时,我会把能直接用于面试回答的核心话术放在最前面,然后再展开详细解析。
面试回答核心话术(可直接用于面试)
“Java 容器我分为单列和双列。单列 List 追求快速随机访问用 ArrayList,头尾操作多用 LinkedList;Set 基于 HashMap 实现,去重依赖 hashCode 和 equals。双列 Map 中,HashMap 是核心,1.8 用尾插法解决了死循环,ConcurrentHashMap 用 CAS + synchronized 实现高并发安全,扩容时多线程协同迁移。我还熟悉红黑树的树化条件,以及 LinkedHashMap 实现 LRU 缓存的原理。线程安全上,我不再用 Hashtable 或 Vector,而是用 ConcurrentHashMap 和并发集合,迭代时注意 fail-fast 机制。整体看,容器框架体现了接口与实现分离的设计思想,选型时数据结构和并发安全必须同时考虑。”
详细解析(支撑上述话术的知识点)
一、容器总体架构
Java 容器分为两大根接口:
- Collection(单列):下分 List(有序可重复)、Set(无序不可重复)、Queue(队列)。
- Map(双列):存储键值对,代表是 HashMap、TreeMap、ConcurrentHashMap。
二、List 家族
| 实现类 | 底层结构 | 随机访问 | 插入删除 | 扩容 | 线程安全 |
|---|---|---|---|---|---|
| ArrayList | Object[]数组 | O(1) | O(n) | 1.5 倍 | 不安全 |
| LinkedList | 双向链表 | O(n) | O(1) | 无 | 不安全 |
| Vector | Object[]数组 | O(1) | O(n) | 2 倍 | 安全(已弃用) |
| CopyOnWriteArrayList | 写时复制数组 | O(1) | O(n) | 无 | 安全(读多写少) |
关键点:
ArrayList默认容量 10,扩容调用Arrays.copyOf。- 迭代时使用集合自身的
remove/add会触发ConcurrentModificationException(fail-fast),安全删除要用iterator.remove()。
三、Set 家族
| 实现类 | 底层实现 | 顺序 | 判重依据 |
|---|---|---|---|
| HashSet | HashMap(key 存元素,value 为PRESENT常量) | 无序 | hashCode()+equals() |
| LinkedHashSet | LinkedHashMap | 插入顺序 | 同上 |
| TreeSet | TreeMap(红黑树) | 排序 | compareTo()或Comparator |
关键点:
- 自定义类放入
HashSet必须同时重写hashCode和equals。 TreeSet要求元素实现Comparable或传入Comparator。
四、Map 家族(核心)
1. HashMap
- 底层:数组 + 链表 + 红黑树。
- put 流程:哈希扰动 → 定位桶 → 链表尾插/红黑树插入 → 检查扩容。
- 扩容:2 倍扩容,
hash & oldCap判断高低位迁移,尾插法避免 1.7 的死循环。 - 树化条件:链表长度 ≥ 8且数组长度 ≥ 64(否则优先扩容)。
- 容量为 2 的幂:用
hash & (n-1)替代取模,效率高。
2. ConcurrentHashMap
- JDK 1.8 实现:CAS + synchronized,抛弃 1.7 的 Segment 分段锁。
- put 流程:空桶 CAS 插入 → 非空桶 synchronized 锁头节点 → 遇到扩容则协助迁移。
- 扩容:多线程协同,按步长领取任务,
ForwardingNode标记已迁移桶,读请求自动转发。 - 读操作:完全无锁,
val和next都用volatile保证可见性。
3. LinkedHashMap
- 在
HashMap基础上加双向链表维护顺序。 - 设置
accessOrder = true可实现LRU 缓存(重写removeEldestEntry)。
4. TreeMap
- 底层红黑树,key 有序,支持范围查找。
五、线程安全选择
| 场景 | 推荐容器 |
|---|---|
| 随机访问多,尾插多 | ArrayList |
| 频繁头尾增删 | LinkedList或ArrayDeque |
| 去重 | HashSet/TreeSet |
| 键值快速存取 | HashMap |
| 需排序 | TreeMap/TreeSet |
| 高并发读写 | ConcurrentHashMap |
| 读多写少线程安全 | CopyOnWriteArrayList |
原则:不再用Hashtable或Vector,用ConcurrentHashMap和 JUC 并发集合代替。