Wrayの知识库 Wrayの知识库
首页
  • Java 基础
  • Java 集合
  • Java 并发
  • Java IO
  • JVM
  • Spring Framework
  • Spring Boot
  • Spring Cloud
  • Spring Security
  • MySQL
  • Redis
  • 计算机基础
  • 操作系统原理
  • Linux
  • MacOS
  • Windows
  • 系统工程与研究专题
  • AI 基础
  • 大模型基础
  • Prompt 工程
  • RAG 检索增强生成
  • Agent 智能体
  • AI 应用开发
  • AI 工程化
  • AI 安全与治理
  • AI 面试与设计题
  • 纸质书
  • 电子书
  • 学习课程
疑难杂症
GitHub (opens new window)
首页
  • Java 基础
  • Java 集合
  • Java 并发
  • Java IO
  • JVM
  • Spring Framework
  • Spring Boot
  • Spring Cloud
  • Spring Security
  • MySQL
  • Redis
  • 计算机基础
  • 操作系统原理
  • Linux
  • MacOS
  • Windows
  • 系统工程与研究专题
  • AI 基础
  • 大模型基础
  • Prompt 工程
  • RAG 检索增强生成
  • Agent 智能体
  • AI 应用开发
  • AI 工程化
  • AI 安全与治理
  • AI 面试与设计题
  • 纸质书
  • 电子书
  • 学习课程
疑难杂症
GitHub (opens new window)
  • Java章节编写规范
  • Java基础

  • Java集合

    • Java集合概述
      • 1. 集合框架解决什么问题
      • 2. 集合接口体系
      • 3. Iterable 与 Iterator
      • 4. List
      • 5. Set
      • 6. Map
      • 7. Queue 与 Deque
      • 8. 时间复杂度总览
      • 9. fail-fast 与 fail-safe
      • 10. 线程安全
      • 11. 不可变集合与只读视图
      • 12. 集合选型速查
      • Tips 快问快答
    • ArrayList
    • LinkedList
    • HashMap
    • LinkedHashMap
    • HashSet
    • TreeMap
    • Queue&Deque
    • 迭代器与遍历机制
    • Collections工具类
    • 集合排序与比较器
    • 集合选型与常见问题
  • Java并发

  • Java IO

  • JVM

目录

Java集合概述

Java 集合框架是 Java 标准库中最常用的基础设施之一。它提供了一组接口、实现类和工具方法,用于存储、查找、排序、去重、排队、映射关系和批量处理数据。

学习集合不能只记住“ArrayList 查询快、LinkedList 增删快、HashMap 查找快”这类结论。真正有价值的是理解:

  • 集合接口之间的职责边界。
  • 不同实现类的底层数据结构。
  • 时间复杂度背后的原因。
  • 扩容、哈希冲突、红黑树、迭代器、fail-fast 等机制。
  • 开发中如何选型,如何避免常见坑。

# 1. 集合框架解决什么问题

数组长度固定、API 较少,适合结构简单、长度稳定的场景。业务开发中更多时候需要动态数据结构:

用户列表        -> List
唯一用户 ID     -> Set
用户 ID 到用户  -> Map
待处理任务      -> Queue
最近访问记录    -> LinkedHashMap
优先级任务      -> PriorityQueue

集合框架将常见数据结构封装成统一 API,使业务代码不需要从零实现数组扩容、链表操作、哈希表、树结构和排序算法。

# 2. 集合接口体系

Java 集合分为两条主线:

  • Collection:单个元素的集合。
  • Map:键值对映射,不继承 Collection。
Iterable
└─ Collection
   ├─ List
   │  ├─ ArrayList
   │  └─ LinkedList
   ├─ Set
   │  ├─ HashSet
   │  ├─ LinkedHashSet
   │  └─ TreeSet
   └─ Queue
      ├─ Deque
      │  ├─ ArrayDeque
      │  └─ LinkedList
      └─ PriorityQueue

Map
├─ HashMap
├─ LinkedHashMap
├─ TreeMap
├─ Hashtable
└─ ConcurrentHashMap

接口职责:

接口 数据语义 是否允许重复 是否有序 典型实现
List 线性表 允许 按索引有序 ArrayList、LinkedList
Set 不重复集合 不允许 取决于实现 HashSet、TreeSet
Queue 队列 通常允许 按出队规则 LinkedList、PriorityQueue
Deque 双端队列 通常允许 两端操作 ArrayDeque、LinkedList
Map 键值映射 key 不重复 取决于实现 HashMap、TreeMap

# 3. Iterable 与 Iterator

Iterable 让集合支持增强 for 循环。

for (String name : names) {
    System.out.println(name);
}

编译后大致等价于:

Iterator<String> iterator = names.iterator();
while (iterator.hasNext()) {
    String name = iterator.next();
    System.out.println(name);
}

迭代模型:

Collection
   │ iterator()
   ▼
Iterator
   │ hasNext / next / remove
   ▼
逐个访问元素

集合遍历时删除元素,应优先使用迭代器的 remove(),不要直接调用集合的 remove()。

# 4. List

List 表示有序、可重复、可按索引访问的集合。

List<String> names = new ArrayList<>();
names.add("Tom");
names.add("Tom");
System.out.println(names.get(0));

常见实现对比:

实现 底层结构 随机访问 头尾操作 中间插入删除 内存占用
ArrayList 动态数组 快,O(1) 尾部快 需要移动元素 较低
LinkedList 双向链表 慢,O(n) 头尾快 找到节点后快 较高

实际业务中,ArrayList 往往是默认首选。很多人以为 LinkedList 插入删除一定更快,但如果插入删除前还要按索引定位节点,整体仍然是 O(n),而且链表节点对象带来额外内存和缓存不友好问题。

# 5. Set

Set 表示不重复集合。

Set<Long> userIds = new HashSet<>();
userIds.add(1L);
userIds.add(1L);
System.out.println(userIds.size()); // 1

常见实现:

实现 底层结构 顺序 适合场景
HashSet HashMap 不保证顺序 快速去重、快速判断存在
LinkedHashSet LinkedHashMap 插入顺序 去重并保留插入顺序
TreeSet 红黑树 排序 去重并排序、范围查询

Set 判断重复依赖元素的相等语义。对于 HashSet,重点是 equals 和 hashCode;对于 TreeSet,重点是 compareTo 或 Comparator。

# 6. Map

Map 用于保存 key 到 value 的映射。

Map<Long, User> userMap = new HashMap<>();
userMap.put(1L, new User("Tom"));
User user = userMap.get(1L);

常见实现:

实现 底层结构 key 顺序 典型场景
HashMap 数组 + 链表/红黑树 不保证 默认映射结构
LinkedHashMap HashMap + 双向链表 插入或访问顺序 有序遍历、LRU
TreeMap 红黑树 key 排序 排序、范围查询
ConcurrentHashMap 并发哈希表 不保证 并发读写

Map 的常用方法:

方法 作用
put 添加或覆盖 key 对应 value
get 根据 key 获取 value
remove 删除 key
containsKey 判断 key 是否存在
computeIfAbsent key 不存在时计算并放入
putIfAbsent key 不存在时放入
merge 合并旧值和新值

get(key) == null 不能直接说明 key 不存在,因为 value 也可能就是 null。需要区分时使用 containsKey。

# 7. Queue 与 Deque

Queue 表示队列,常见语义是先进先出。

入队 offer
   │
   ▼
[A, B, C]
   │
   ▼
出队 poll -> A

Deque 是双端队列,两端都能进出:

addFirst       addLast
   │             │
   ▼             ▼
[ head ... tail ]
   ▲             ▲
pollFirst     pollLast

栈场景优先使用 ArrayDeque,不要再使用老的 Stack 类。

# 8. 时间复杂度总览

操作 ArrayList LinkedList HashMap TreeMap HashSet
随机访问 O(1) O(n) 不适用 不适用 不适用
尾部添加 均摊 O(1) O(1) 不适用 不适用 不适用
中间插入 O(n) O(n) 定位 + O(1) 插入 不适用 不适用 不适用
查找元素 O(n) O(n) 平均 O(1) O(log n) 平均 O(1)
删除元素 O(n) O(n) 平均 O(1) O(log n) 平均 O(1)
有序遍历 按插入顺序 按链表顺序 不保证 key 排序 不保证

复杂度是平均模型,不是绝对承诺。哈希冲突、扩容、比较器成本、对象分布、CPU 缓存命中都会影响真实性能。

# 9. fail-fast 与 fail-safe

很多集合迭代器是 fail-fast 的。遍历过程中如果集合被非迭代器方式结构性修改,可能抛出 ConcurrentModificationException。

for (String name : names) {
    if (name.startsWith("A")) {
        names.remove(name); // 可能抛 ConcurrentModificationException
    }
}

正确方式:

Iterator<String> iterator = names.iterator();
while (iterator.hasNext()) {
    String name = iterator.next();
    if (name.startsWith("A")) {
        iterator.remove();
    }
}

机制:

集合结构修改 -> modCount + 1
迭代器创建时记录 expectedModCount
迭代时比较两者
不同 -> ConcurrentModificationException

fail-fast 是尽早发现错误的机制,不是线程安全保证。

# 10. 线程安全

大多数普通集合都不是线程安全的:

  • ArrayList
  • LinkedList
  • HashMap
  • HashSet
  • TreeMap

多线程读写时选择:

场景 推荐
高并发 Map ConcurrentHashMap
读多写少 List CopyOnWriteArrayList
阻塞队列 ArrayBlockingQueue、LinkedBlockingQueue
简单同步包装 Collections.synchronizedList
不可变数据共享 List.of、Map.of 或不可变副本

同步包装集合在遍历时仍需要外部同步:

List<String> list = Collections.synchronizedList(new ArrayList<>());

synchronized (list) {
    for (String value : list) {
        System.out.println(value);
    }
}

# 11. 不可变集合与只读视图

Collections.unmodifiableList(list) 返回只读视图,不是不可变副本。

List<String> source = new ArrayList<>();
List<String> view = Collections.unmodifiableList(source);

source.add("A");
System.out.println(view); // [A]

view 自己不能修改,但底层 source 变了,视图也会变。

如果需要不可变副本:

List<String> copy = List.copyOf(source);

或者:

List<String> list = List.of("A", "B");

注意:List.of、Set.of、Map.of 不允许 null。

# 12. 集合选型速查

需求 推荐
有序可重复列表 ArrayList
频繁头尾入队出队 ArrayDeque
快速去重 HashSet
去重并保持插入顺序 LinkedHashSet
去重并排序 TreeSet
key-value 查找 HashMap
key-value 且保持插入顺序 LinkedHashMap
key-value 且按 key 排序 TreeMap
并发 key-value ConcurrentHashMap
生产消费队列 BlockingQueue

默认经验:

  • List 默认选 ArrayList。
  • 栈和队列默认选 ArrayDeque。
  • Map 默认选 HashMap。
  • 需要顺序时再换 LinkedHashMap 或 TreeMap。
  • 并发场景不要靠普通集合硬撑。

# Tips 快问快答

Q:Collection 和 Collections 有什么区别? A:Collection 是集合根接口,Collections 是集合工具类。

Q:Map 是 Collection 的子接口吗? A:不是。Map 是键值对结构,与 Collection 平行。

Q:List、Set、Map 怎么快速区分? A:List 管顺序和重复,Set 管唯一性,Map 管 key 到 value 的映射。

Q:为什么集合里不能放基本类型? A:泛型类型参数必须是引用类型,所以用 Integer、Long 等包装类。

Q:遍历时删除元素为什么会报错? A:普通集合迭代器检测到结构性修改后会 fail-fast。

Q:fail-fast 能保证并发安全吗? A:不能。它只是错误检测机制,不是同步机制。

Q:List.of 创建的集合能修改吗? A:不能,它返回不可变集合,并且不允许 null。

Q:Collections.unmodifiableList 是不可变集合吗? A:严格说不是,它是只读视图,底层集合变化时视图也会变化。

Q:集合选型最重要看什么? A:看是否需要顺序、是否允许重复、是否按 key 查找、是否并发、是否需要排序。

Q:为什么很多场景默认用 ArrayList? A:它结构简单、随机访问快、内存局部性好,绝大多数业务列表都适合。

上次更新: 2026/06/24, 16:37:44
Java现代语法特性
ArrayList

← Java现代语法特性 ArrayList→

Copyright © 2023-2026 Wray | 鄂ICP备2024050235号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式