Java集合类型主要有哪些?以及各自原理

Java 集合框架在顶层设计上分为两大核心接口体系:Collection(存储单一元素)和 Map(存储键值对)。

1. List 体系(有序、可重复)

  • ArrayList
    • 底层原理 :基于动态数组实现。内存空间连续,支持通过索引进行 O(1) 时间复杂度的随机访问。
    • 扩容机制 :默认初始容量为 10(懒加载,首次 add 时初始化)。当容量不足时,触发扩容机制,新容量计算公式通常为 oldCapacity + (oldCapacity >> 1),即扩容为原容量的 1.5 倍 。扩容涉及底层数组的内存拷贝(System.arraycopy),开销较大。
  • LinkedList
    • 底层原理 :基于双向链表实现。内存空间不连续,每个节点(Node)包含数据项以及指向前驱和后继节点的指针。
    • 性能特征:不支持高效的随机访问,查找元素需遍历链表,时间复杂度为 O(n)。但在已知节点位置的情况下,插入和删除操作只需修改指针,时间复杂度为 O(1)

2. Set 体系(无序、不可重复)

  • HashSet
    • 底层原理 :内部完全包装了一个 HashMap。存入 HashSet 的元素被当作底层 HashMap 的 Key,而 Value 则统一指向一个静态不变的 Object 实例(PRESENT)。
    • 去重机制 :依赖 HashMap 的 Key 唯一性特质。存入元素时,依赖元素的 hashCode()equals() 方法判断是否重复。
  • TreeSet
    • 底层原理 :内部封装了 TreeMap,底层数据结构为红黑树(Red-Black Tree)
    • 排序机制 :元素必须实现 Comparable 接口,或者在构造时传入自定义的 Comparator。红黑树保证了元素在插入、删除、查找时均能维持 O(\\log n) 的时间复杂度,并保持严格的有序状态。

3. Map 体系(键值对)

  • HashMap (JDK 1.8)
    • 底层原理 :采用 数组 + 链表 + 红黑树 的混合结构。
    • 寻址算法 :向 Map 中 put 元素时,先计算 Key 的扰动 Hash 值(hash() ^ (hash() >>> 16)),然后通过 (n - 1) & hash(等价于取模运算,但位运算性能更高,前提是数组长度 n 必须是 2 的幂次方)定位到数组的槽位(Bucket)。
    • 冲突解决与树化 :发生哈希冲突时采用尾插法形成链表。当某一槽位的链表长度达到 8 且底层数组长度大于 64 时,链表将转化为红黑树,以保证在极端冲突下的查询时间复杂度从 O(n) 优化至 O(\\log n)
    • 扩容机制 :默认负载因子为 0.75。当 size > capacity * 0.75 时触发扩容,容量翻倍(2倍)。扩容时,元素位置要么保持在原槽位,要么移动到 原索引 + 原数组容量 的新槽位,避免了重新计算全部 Hash。
  • HashMap (JDK 1.8 以前)
    • 底层原理 :数据结构采用 数组 + 链表 。内部维护一个 Entry 数组,通过计算 Key 的 Hash 值来确定其在数组中的索引位置。当发生 Hash 冲突时,将新的键值对通过链表结构存储在对应的桶(Bucket)中。
    • 并发安全问题 :由于没有并发控制机制,在多线程环境下进行扩容(Resize)操作时,由于采用 头插法 (Head Insertion) 移动链表节点,可能会导致链表成环 ,从而在后续的 get 操作中引发死循环,导致 CPU 占用率飙升。此外,还存在数据覆盖丢失的风险。
    • 1.7 是头插法 (新节点插入链表头部),1.8 改为尾插法(新节点插入链表尾部),从而解决了扩容死循环的问题
    • 1.7 在发生大量 Hash 冲突时,链表过长会导致查询效率从 O(1) 退化为 O(n),而 1.8 引入红黑树将其优化为 O(\\log n)
  • ConcurrentHashMap (JDK 1.8)
    • 底层原理 :数据结构与 HashMap 保持一致(数组 + 链表 + 红黑树)。
    • 并发控制机制 :彻底废弃了 JDK 1.7 的分段锁(Segment),转而采用 CAS + synchronized 来实现极细粒度的锁。在进行 put 操作时,如果槽位为空,利用 CAS 操作无锁插入;如果槽位非空,则只对该槽位的首节点(链表头节点或红黑树根节点)加 synchronized 锁,这使得不同槽位之间的写入操作可以完全并发执行
  • ConcurrentHashMap (JDK 1.7)
    • 底层原理 :数据结构采用 Segment 数组 + HashEntry 数组 + 链表 。一个 ConcurrentHashMap 实例中包含由多个 Segment 组成的数组,每个 Segment 内部又维护着一个类似于 HashMap 的 HashEntry 数组
    • 并发控制机制 :核心思想是 分段锁 (Segment Locking) 。每个 Segment 继承了 ReentrantLock,从而充当锁的角色。在进行 put 操作时,程序会首先通过 Hash 定位到具体的 Segment,只对该 Segment 加锁,而不影响其他 Segment 的读写 。这意味着只要多个写入操作发生在不同的段中,它们就可以完全并行执行,默认支持 16 个线程并发写入。
    • 因为是继承自ReentrantLock,因此就有大量的AQS相关的队列,因此浪费很大很大
相关推荐
小欣加油13 分钟前
leetcode287寻找重复数
数据结构·c++·算法·leetcode
尽兴-43 分钟前
2.1 向量基础:Embedding、余弦相似度、欧氏距离、向量检索
算法·embedding·欧氏距离·向量检索·余弦相似度
Black蜡笔小新1 小时前
自动化AI算法训练服务器DLTM训推一体工作站赋能多行业智能化升级
人工智能·算法·自动化
怪兽学LLM1 小时前
LeetCode 438 找到字符串中所有字母异位词(Python 固定滑动窗口+字符计数解法)
python·算法·leetcode
满怀冰雪2 小时前
第04篇-双指针算法-从有序数组到回文判断的高频解法
java·算法
CC数学建模2 小时前
2026年江西省研究生数学建模竞赛1题:空间数据分析中的过拟合识别完整思路、代码、模型、文章,全网首发高质量分享!
python·算法·数学建模
leo__5202 小时前
MATLAB实现牧羊人算法
开发语言·算法·matlab
Gauss松鼠会2 小时前
【GaussDB】GaussDB SMP特性调优详解
java·服务器·前端·数据库·sql·算法·gaussdb
Tisfy2 小时前
LeetCode 3689.最大子数组总值 I:What The Medium
算法·leetcode·题解·贪心·模拟·脑筋急转弯
葬送的代码人生2 小时前
JavaScript 数组完全指南:从入门到实战
前端·javascript·算法