Skip to content

集合面试题:高频问题与解答

Q1:ArrayList vs LinkedList?

操作ArrayListLinkedList
随机访问O(1)O(n)
头部插入O(n)O(1)
尾部插入O(1)O(1)
中间插入O(n)O(n)
CPU 缓存友好不友好

结论:大多数场景用 ArrayList;只有头插/头删极多时才考虑 LinkedList。


Q2:HashMap 底层实现?

JDK 1.7:数组 + 链表(头插法)
JDK 1.8+:数组 + 链表/红黑树(尾插法)

关键参数:

参数
默认容量16
负载因子0.75
链表转红黑树阈值8
红黑树转链表阈值6

为什么是 8 和 6?泊松分布:负载因子 0.75 时链表长度达到 8 的概率极低,设为阈值是防止哈希攻击。


Q3:HashMap put 流程?

put("hello", 1) 时:

1. 计算 hash = hash("hello")
2. 计算 index = hash & (capacity - 1)
3. bucket[index] 为空?→ 直接插入 Node
4. bucket[index] 不为空?
   - key 相同 → 替换旧值
   - 红黑树节点 → 插入树
   - 链表 → 遍历,找到相同 key 替换;否则尾插
5. 链表长度 ≥ 8 → 转红黑树
6. size > threshold → 扩容

Q4:HashMap vs ConcurrentHashMap?

特性HashMapConcurrentHashMap
线程安全
null 支持✅ key/value 都可 null❌ 都不行
锁粒度无锁分段锁 / CAS(JDK 8+)
迭代安全Fail-FastFail-Safe

Q5:HashSet 底层实现?

HashSet = HashMap 的 key 集合,value 用一个固定对象 PRESENT 填充。

java
public class HashSet<E> {
    private transient HashMap<E, Object> map;
    private static final Object PRESENT = new Object();

    public boolean add(E e) {
        return map.put(e, PRESENT) == null;
    }
}

所以 HashSet 的所有特性都继承自 HashMap。


Q6:fail-fast vs fail-safe?

机制集合特点
Fail-FastArrayList、HashMap遍历时修改 → 抛异常
Fail-SafeCopyOnWriteArrayList、ConcurrentHashMap遍历副本,不抛异常

Fail-Fast 的原理:每个集合维护 modCount,迭代器创建时记录 expectedModCount,每次 next() 检查是否一致。


Q7:HashMap 扩容机制?

容量翻倍:16 → 32 → 64 → 128...

新位置计算(高位分流):
  hash & oldCap == 0 → 原位置不变
  hash & oldCap != 0 → 新位置 = 原位置 + oldCap

为什么高位分流更快?不需要重新计算所有元素的 hash,直接用 hash 的高位决定。


Q8:equals 和 hashCode 的契约?

相等的对象必须有相等的 hashCode。

java
class Student {
    String name;
    int age;

    // 必须同时重写
    @Override
    public boolean equals(Object o) { ... }
    @Override
    public int hashCode() { return Objects.hash(name, age); }
}

HashSet/HashMap 的判断逻辑:先比 hashCode,再比 equals


Q9:如何实现线程安全?

场景推荐
高并发 MapConcurrentHashMap
高并发 ListConcurrentLinkedQueue
读多写少 ListCopyOnWriteArrayList
偶尔并发Collections.synchronizedList
生产者-消费者BlockingQueue

Q10:TreeMap vs HashMap?

特性TreeMapHashMap
有序性✅ 按 key 排序❌ 无序
查找速度O(log n)O(1) 均摊
导航操作✅ first/last/subMap❌ 不支持
key 要求必须可比较任意

总结

核心要点掌握程度
ArrayList vs LinkedList理解适用场景
HashMap 底层结构能画图说明
HashMap put 流程能手写伪代码
扩容机制理解高位分流
fail-fast 原理理解 modCount
线程安全方案知道各自适用场景

相关链接

基于 VitePress 构建