Skip to content

集合面试题

1. HashMap 的底层原理?

JDK 1.8 中 HashMap 采用 数组 + 链表 + 红黑树 的数据结构。

  • 通过 key 的 hashCode 计算数组下标
  • 哈希冲突时,链表长度 < 8 用链表存储,>= 8 且数组长度 >= 64 时转为红黑树
  • 默认负载因子 0.75,容量达到 75% 时扩容为原来的 2 倍
  • 扩容时重新计算每个元素的位置

2. HashMap 为什么线程不安全?

  • JDK 1.7 中,扩容时头插法可能导致环形链表,造成死循环
  • JDK 1.8 中,多线程 put 可能导致数据覆盖,造成数据丢失
  • 并发环境下建议使用 ConcurrentHashMap

3. ConcurrentHashMap 如何保证线程安全?

JDK 1.7:采用分段锁(Segment),默认 16 个 Segment,每个 Segment 独立加锁,最大支持 16 个线程并发写入。

JDK 1.8:采用 CAS + synchronized 实现,锁粒度更细,只锁住链表或红黑树的首节点。put 时:

  1. 计算数组下标,若该位置为 null,使用 CAS 插入
  2. 若不为 null,使用 synchronized 锁住首节点,进行插入操作

4. ArrayList 和 LinkedList 的区别?

特性ArrayListLinkedList
底层实现动态数组双向链表
随机访问O(1)O(n)
增删(头尾)O(n)O(1)
内存占用连续内存额外存储前后指针
适用场景查询多增删多

5. HashSet 如何保证元素不重复?

HashSet 底层基于 HashMap 实现,元素作为 HashMap 的 key 存储,value 是一个固定的 Object 对象。利用 HashMap 的 key 唯一性保证元素不重复。