Java

Java 集合框架与数据结构核心速记笔记

2026-06-26 #Java#Java集合

核心总览:本笔记系统梳理了 Java 集合框架及线性数据结构的底层原理、并发控制、性能特征与适用场景。核心法则是:单线程重性能,高并发重安全,读多写少用并发,排序有序选树链。


一、List 接口实现类(有序可重复)

集合类 底层结构 线程安全 核心特性与适用场景 典型实战用法
ArrayList 数组 查询极快 (O(1)) ,增删慢 (O(n))。适合查询多、增删少的单线程场景。 数据库批量查询结果遍历展示;预分配容量 new ArrayList<>(1000) 避免频繁扩容。
LinkedList 双向链表 头尾增删快 (O(1)) ,查询慢 (O(n))。适合频繁两端操作。 实现队列/栈(但推荐用 ArrayDeque);严禁用 get(i) 做随机访问
CopyOnWriteArrayList 数组(写时复制) 读无锁,写复制整个数组。适合读多写少的并发场景。 事件监听器列表(如 Dubbo 服务通知、ZooKeeper Watcher);避免频繁写或大列表写
Vector 数组 是(过时) 方法全 synchronized,性能差。 基本淘汰,仅用于兼容老旧遗留系统。

一、List 接口实现类(有序可重复)

集合类 底层结构 线程安全 核心特性与适用场景 典型实战用法
ArrayList 数组 查询极快 (O(1)) ,增删慢 (O(n))。适合查询多、增删少的单线程场景。 数据库批量查询结果遍历展示;预分配容量 new ArrayList<>(1000) 避免频繁扩容。
LinkedList 双向链表 头尾增删快 (O(1)) ,查询慢 (O(n))。适合频繁两端操作。 实现队列/栈(但推荐用 ArrayDeque);严禁用 get(i) 做随机访问
CopyOnWriteArrayList 数组(写时复制) 读无锁,写复制整个数组。适合读多写少的并发场景。 事件监听器列表(如 Dubbo 服务通知、ZooKeeper Watcher);避免频繁写或大列表写
Vector 数组 是(过时) 方法全 synchronized,性能差。 基本淘汰,仅用于兼容老旧遗留系统。

二、Map 接口实现类(键值对映射)

集合类 底层结构 线程安全 核心特性与适用场景 典型实战用法
HashMap 数组+链表/红黑树 存取基本 O(1),允许 null 键/值。最通用的 Map。 单线程下的键值缓存、映射关系存储;高并发下会导致环形链表或数据丢失
ConcurrentHashMap 数组+链表/红黑树 高并发首选。JDK 8 用 CAS + synchronized 锁桶头,吞吐量极高。 微服务注册中心缓存元数据、管理连接;Key/Value 均不允许为 null
Hashtable 数组+链表 是(过时) 方法全 synchronized,全局一把锁,并发性能极差。 已淘汰,用 ConcurrentHashMap 替代。
LinkedHashMap 哈希表+双向链表 维护插入顺序访问顺序 实现 LRU 缓存(重写 removeEldestEntry),如 MyBatis 缓存。
TreeMap 红黑树 按 Key 自然排序或定制排序,查找 O(log n)。 排行榜、区间查询(如按时间戳查日志 subMap)。
WeakHashMap 哈希表 Key 为弱引用,GC 时自动回收。 监听器注册表,防止内存泄漏(外部引用消失,Map 自动清理)。
IdentityHashMap 数组(线性探测) == 而非 equals 判断 Key 相等。 AOP 代理对象映射、目标对象追踪(如 Spring 内部实现)。

三、Set 接口实现类(去重)

Set 内部依赖 Map 实现,利用 Key 不可重复特性。

  • HashSet:基于 HashMap,存取 O(1),不保序。用于常规去重(如标签、ID)。
  • LinkedHashSet:基于 LinkedHashMap,维护插入顺序。
  • TreeSet:基于 TreeMap,支持自然排序或定制排序。

四、队列与栈

类别 推荐实现 核心特性 典型场景
双端队列(栈/队列) ArrayDeque 数组实现,比 LinkedList 和 Stack 更快更省内存。 JVM 方法调用栈、线程池任务队列。
无锁并发队列 ConcurrentLinkedQueue 无锁高吞吐。 高并发生产者-消费者模型。
有界阻塞队列 ArrayBlockingQueue 满时阻塞生产者,空时阻塞消费者。 资源池、任务队列(如 Tomcat 工作线程),防内存溢出
无界阻塞队列 LinkedBlockingQueue 吞吐量高于 Array,默认容量极大。 Executors.newFixedThreadPool 的底层队列。
直接交接队列 SynchronousQueue 不存储元素,生产者必须等消费者接收。 Executors.newCachedThreadPool,任务即时处理。
延迟队列 DelayQueue 元素到期才能取出。 定时任务调度、订单超时关闭。
优先级队列 PriorityBlockingQueue 按优先级出队(堆实现)。 优先级消息处理。

五、基础数据结构对比

维度 数组 (如 ArrayList) 链表 (如 LinkedList)
内存布局 连续内存,大小固定 分散内存,靠指针相连
访问效率 随机访问 O(1) 随机访问 O(n),需遍历
增删效率 中间增删 O(n),需挪动数据 增删 O(1) (前提是已定位到位置)
空间开销 仅存数据,内存紧凑 需存前后指针,开销较大

六、核心原理与底层机制

1. HashMap 核心机制

  • 定位桶(n - 1) & hash(容量必为 2 的幂,位运算替代取模,极速)。
  • 树化机制:链表长度 > 8 数组长度 >= 64 时,链表转红黑树(查找从 O(n) 提升到 O(log n));树节点 < 6 时退回链表。
  • 扩容机制:默认容量 16,负载因子 0.75(size > 16*0.75=12 时触发),扩容为原 2 倍,需重新计算所有元素位置。
  • 性能优化:预估数据量时指定初始容量(如存 1000 个元素,设 new HashMap<>(2048)),避免频繁扩容。

2. 线程安全与并发控制

  • ConcurrentHashMap (JDK 8+) :摒弃 Segment,采用 CAS + synchronized,仅锁链表/红黑树头节点,并发度极高;读操作无锁(靠 volatile 保证可见性)。
  • CopyOnWriteArrayList:写操作加锁并复制整个数组,读操作无锁;缺点:写代价高,内存占用大,数据弱一致性。

3. Fail-Fast 机制

  • 集合内部维护 modCount,遍历期间若结构被修改,迭代器比对发现不一致则抛出 ConcurrentModificationException
  • 安全删除:遍历时删除必须用 iterator.remove(),或直接使用并发容器。

七、实战避坑指南(⭐ 重点牢记)

  1. ArrayList 必预分配:已知大小时 new ArrayList<>(capacity),避免多次 1.5 倍扩容和数组拷贝。
  2. 禁用 LinkedList 的 get(i) :链表随机访问是 O(n),性能极差。
  3. CopyOnWriteArrayList 忌频繁写:写操作全量复制,大列表或高频写场景会拖垮性能。
  4. 遍历时安全删除:严禁 list.remove(obj),必须用迭代器的 remove()
  5. HashMap 忌并发写:多线程 put 会导致环形链表和数据丢失,务必用 ConcurrentHashMap。
  6. 重写 equals 必重写 hashCode:否则 HashMap/HashSet 中逻辑相同的对象会被当成两个 Key,导致存取失败。
  7. ConcurrentHashMap 不允许 null:Key/Value 均不能为 null,避免 containsKeyget 歧义。
  8. 别用过时类:Stack(用 ArrayDeque)、Hashtable(用 ConcurrentHashMap)、Vector(用 CopyOnWriteArrayList)。
  9. HashMap 容量设 2 的幂:保证 hash & (n-1) 等效取模且分布均匀,减少哈希冲突。
评论
分享