Java集合框架详解

Java 集合框架详解(Java Collections Framework)

Java 集合框架(JCF)是 Java SE 中最核心的部分之一,位于 java.util 包下。它提供了一套统一的接口、抽象类和实现类,用于存储、管理和操作对象的集合(如列表、集合、映射等)。集合框架的核心目标是:高效类型安全易扩展

本文将从基础到高级,系统详解集合框架,包括架构、核心接口/类、常用方法、线程安全、性能分析、源码要点、常见问题及最佳实践。基于 Java 17+(2026 主流版本)的视角,结合实际开发经验。

一、集合框架整体架构

集合框架分为两大体系:

  1. Collection 接口:单值集合(元素是单个对象)。
  • 子接口:List(有序、可重复)、Set(无序、不重复)、Queue(队列)、Deque(双端队列)。
  1. Map 接口:键值对集合(key-value pairs,不继承 Collection)。

抽象类(如 AbstractList、AbstractSet)提供骨架实现,方便自定义扩展。

核心类图简述(文字版):

Collection (接口)
├── List (接口)
│   ├── ArrayList
│   ├── LinkedList
│   └── Vector (遗留)
├── Set (接口)
│   ├── HashSet
│   ├── LinkedHashSet
│   └── TreeSet (SortedSet/NavigableSet)
├── Queue (接口)
│   ├── PriorityQueue
│   └── ArrayDeque (Deque 接口实现)
└── Map (接口)
    ├── HashMap
    ├── LinkedHashMap
    ├── TreeMap (SortedMap/NavigableMap)
    └── Hashtable (遗留)
  • 辅助类:Collections(工具类,提供排序、同步等)、Arrays(数组工具)。

二、核心接口与实现类详解

1. List 接口(有序、可重复)

  • 特点:支持索引访问、允许重复元素。
  • 常用实现
  • ArrayList(首选):底层动态数组(Object[]),随机访问 O(1),扩容机制(1.5 倍增长)。
  • LinkedList:底层双向链表,支持 Queue/Deque 接口,头尾操作 O(1),随机访问 O(n)。
  • Vector:类似 ArrayList 但线程安全(synchronized),性能差,已过时。

2. Set 接口(无序、不重复)

  • 特点:不允许重复(equals 判断),无索引。
  • 常用实现
  • HashSet:底层 HashMap(key 存元素),O(1) 平均操作。
  • LinkedHashSet:HashSet + 双向链表,保持插入顺序。
  • TreeSet:底层红黑树(TreeMap),自动排序,支持 NavigableSet 接口(ceiling/floor 等)。

3. Queue 接口(先进先出 FIFO)

  • 特点:用于任务调度、缓冲。
  • 常用实现
  • PriorityQueue:底层堆(数组),按优先级出队 O(log n)。
  • ArrayDeque:底层循环数组,双端队列,性能优于 LinkedList。

4. Map 接口(键值对)

  • 特点:key 唯一(equals + hashCode),value 可重复。
  • 常用实现
  • HashMap(首选):JDK8+ 数组 + 链表 + 红黑树(链表 >8 转树),负载因子 0.75。
  • LinkedHashMap:HashMap + 双向链表,支持插入/访问顺序(LRU 缓存)。
  • TreeMap:底层红黑树,按 key 排序,支持 NavigableMap(subMap 等)。
  • Hashtable:线程安全版 HashMap,已过时。

Java 9+ 新增:不可变集合,如 List.of()、Set.of()、Map.of(),用于快速创建只读集合。

三、常用方法汇总(以 Collection 和 Map 为例)

Collection 接口方法

方法类别示例方法描述
添加add(E e), addAll(Collection c)添加元素/集合
删除remove(Object o), clear()删除元素/清空
查询contains(Object o), size(), isEmpty()检查包含/大小/空
遍历iterator(), forEach(Consumer)迭代器/函数式遍历(Java 8+)
转换toArray()转数组

Map 接口方法

方法类别示例方法描述
添加/修改put(K key, V value), putAll(Map m)插入/覆盖键值对
删除remove(Object key), clear()删除键/清空
查询get(Object key), containsKey(K key)获取值/检查键
遍历keySet(), values(), entrySet()获取键集/值集/键值对集
Java 8+ 新增computeIfAbsent, merge函数式操作(如默认值)

示例代码(ArrayList + HashMap):

import java.util.*;

public class CollectionDemo {
    public static void main(String[] args) {
        // List 示例
        List<String> list = new ArrayList<>();
        list.add("apple");
        list.add("banana");
        list.add(1, "orange"); // 插入到索引1
        System.out.println(list.get(0)); // apple

        // Map 示例
        Map<Integer, String> map = new HashMap<>();
        map.put(1, "one");
        map.put(2, "two");
        System.out.println(map.get(1)); // one

        // 遍历
        map.forEach((k, v) -> System.out.println(k + ": " + v));
    }
}

四、线程安全与并发集合

标准集合(如 ArrayList、HashMap)非线程安全,多线程下可能 ConcurrentModificationException。

  • 遗留安全类:Vector、Hashtable(synchronized,全同步,性能低)。
  • 现代推荐(java.util.concurrent 包):
  • ConcurrentHashMap:分段锁 + CAS,读无锁,高并发首选。
  • CopyOnWriteArrayList:写时复制,读无锁,适合读多写少。
  • ConcurrentLinkedQueue:无锁队列,CAS 实现。
  • 同步包装:Collections.synchronizedList(list),但性能不如并发包。

示例

Map<String, String> safeMap = new ConcurrentHashMap<>();
safeMap.putIfAbsent("key", "value"); // 原子操作

五、性能分析与选择指南

性能对比表(平均复杂度)

集合类型添加删除查询遍历空间开销适用场景
ArrayListO(1) 摊销O(n)O(1)O(n)中等随机访问、尾部操作
LinkedListO(1)O(1)O(n)O(n)高(节点)频繁插入/删除
HashSet/MapO(1)O(1)O(1)O(n)中等快速查找、去重
TreeSet/MapO(log n)O(log n)O(log n)O(n)中等排序、范围查询
PriorityQueueO(log n)O(log n)O(1) peekO(n)中等优先级调度
  • HashMap 源码要点:hash = key.hashCode() ^ (h >>> 16),链表转树阈值 8,树转链表阈值 6。
  • 选择决策
  • 列表:99% 用 ArrayList,除非频繁头操作用 LinkedList/ArrayDeque。
  • 集合:去重用 HashSet,需要顺序用 LinkedHashSet,排序用 TreeSet。
  • 映射:普通用 HashMap,顺序用 LinkedHashMap,排序用 TreeMap。
  • 并发:一律 ConcurrentXXX。

六、常见问题与最佳实践

常见问题

  1. ConcurrentModificationException:遍历时修改集合。解决:用 Iterator.remove() 或 CopyOnWrite。
  2. Null 值:HashMap 允许 null key/value,TreeMap 不允许 null key。
  3. 扩容开销:ArrayList 默认容量 10,扩容 1.5 倍。建议预估大小:new ArrayList<>(100)
  4. equals 与 hashCode:自定义类做 key/set 元素,必须重写(否则不唯一)。
  5. 不可变集合:Java 9+ 用 List.of(),避免意外修改。

最佳实践(2026 主流)

  • 接口编程List<T> list = new ArrayList<>();(泛型 + 菱形运算符)。
  • 函数式:用 stream() 处理,如 list.stream().filter(x -> x > 0).collect(Collectors.toList());
  • 大集合:用 Guava 或 Apache Commons 扩展(如 Multimap)。
  • 内存优化:大 Map 用 LinkedHashMap + removeEldestEntry 实现 LRU。
  • 避免遗留:别用 Vector/Hashtable,用并发包代替。
  • 测试:用 JUnit 测试集合行为,尤其是自定义 equals/hashCode。

七、扩展与高级主题

  • Java 8+ 增强:default 方法(如 Map.getOrDefault)、Stream API。
  • 自定义集合:继承 AbstractList 等,实现最小方法。
  • 序列化:集合实现 Serializable,但注意 transient 字段。
  • 与数组:Arrays.asList() 转 List,但固定大小。

集合框架是 Java 开发的基石,熟练掌握能显著提升代码效率和质量。如果想深入某个类源码(如 HashMap 的 resize)、具体示例代码,或与 Kotlin/Scala 集合对比,继续问我~

文章已创建 4466

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部