集合概述与体系
概述
Java 集合框架(Java Collections Framework,JCF)是 JDK 提供的一组容器 API,用于存储和操作一组对象。与数组相比,集合的长度可变、支持丰富的增删改查操作,并且针对不同使用场景提供了多种实现(如有序/无序、允许重复/不允许重复、基于哈希/基于树等)。日常开发中,集合是使用频率极高的基础 API,位于 java.util 包中。
为什么需要集合
数组长度固定,且只支持按索引访问,无法方便地表示「一组会动态增删的元素」或「键值对」等结构。集合框架提供了:
- 可变长度:按需增删元素,无需事先定长。
- 多种结构:列表(有序可重复)、集合(不重复)、键值对(Map)等。
- 统一接口:通过
List、Set、Map等接口编程,可随时更换实现类而不影响业务逻辑。 - 泛型支持:
List<String>、Map<Integer, String>等,类型安全、无需强转。
集合体系结构
Java 集合框架以接口为主、实现类为辅。顶层可划分为两大分支:
- Collection — 单列集合,存储一组元素(每个元素一个对象)。
- Map — 双列集合,存储键值对(key-value),每个元素由键与值组成。
Collection 分支
Collection 是 List、Set、Queue 的父接口,表示「一组对象的容器」。常用子接口与实现类关系可简化为:
| 接口 | 含义 | 常用实现类 | 典型特点 |
|---|---|---|---|
| List | 有序、可重复 | ArrayList、LinkedList | 有下标,可重复,ArrayList 查询快、LinkedList 头尾增删方便 |
| Set | 不重复 | HashSet、LinkedHashSet、TreeSet | 无重复;HashSet 无序,TreeSet 可排序,LinkedHashSet 保持插入顺序 |
| Queue | 队列 | LinkedList、ArrayDeque、PriorityQueue | 先进先出或优先级队列;List/Set/Map 的详细用法见 List、Set、Map 详解 |
记忆要点
- List:像「动态数组」,有顺序、可重复,按索引访问。
- Set:像「数学集合」,不重复;具体是否有序、是否可排序看实现类。
- Map:键值对,键不重复,一个键对应一个值。
Map 分支
Map 不继承 Collection,表示「键 → 值」的映射。常用实现类:
| 实现类 | 典型特点 |
|---|---|
| HashMap | 无序(不保证顺序),键不重复,查询/增删平均 O(1) |
| LinkedHashMap | 在 HashMap 基础上保持插入顺序(或访问顺序) |
| TreeMap | 键按自然顺序或自定义比较器排序 |
体系关系简图
Iterable
|
Collection
/ | \
List Set Queue
| | |
ArrayList HashSet LinkedList / ArrayDeque / ...
LinkedList LinkedHashSet
TreeSet
Map (独立分支)
|
HashMap / LinkedHashMap / TreeMap实际编码时,我们通常面向接口声明变量(如 List<String> list),再在创建时选择具体实现(如 new ArrayList<>()),这样后续若要换成 LinkedList 只需改一行构造代码。
基本示例
示例 1:List —— 有序可重复
java
import java.util.ArrayList;
import java.util.List;
// 面向接口声明,用 ArrayList 实现
List<String> list = new ArrayList<>();
list.add("苹果");
list.add("香蕉");
list.add("苹果"); // 允许重复
System.out.println(list); // [苹果, 香蕉, 苹果]
System.out.println(list.get(1)); // 香蕉,按索引访问示例 2:Set —— 不重复
java
import java.util.HashSet;
import java.util.Set;
Set<String> set = new HashSet<>();
set.add("苹果");
set.add("香蕉");
set.add("苹果"); // 重复元素不会多存一份
System.out.println(set); // [苹果, 香蕉](顺序不保证)示例 3:Map —— 键值对
java
import java.util.HashMap;
import java.util.Map;
Map<String, Integer> map = new HashMap<>();
map.put("语文", 90);
map.put("数学", 85);
map.put("语文", 88); // 同一键会覆盖原值
System.out.println(map.get("语文")); // 88
System.out.println(map); // {语文=88, 数学=85}(顺序不保证)如何选择集合类型
- 需要有序、可重复、按索引访问 → 用 List,一般选 ArrayList;若频繁在头尾增删,考虑 LinkedList。
- 需要不重复、不关心顺序 → Set,常用 HashSet;需要插入顺序用 LinkedHashSet,需要排序用 TreeSet。
- 需要键值对、按键找值 → Map,常用 HashMap;需要键有序用 TreeMap,需要插入顺序用 LinkedHashMap。
注意
上述常用实现类(如 ArrayList、HashSet、HashMap)都是非线程安全的。多线程并发读写同一集合时,应使用并发包中的实现(如 ConcurrentHashMap)或通过同步手段保护,详见 并发。
注意事项
- 使用泛型:强烈建议使用
List<String>、Set<Integer>、Map<K,V>等形式,避免使用原始类型List、Map,以在编译期获得类型检查,详见 泛型在集合中的使用。 - null 与实现类:
ArrayList、HashSet、HashMap允许元素或键为null(HashMap 键仅允许一个null);TreeSet、TreeMap的键不能为null,否则会抛NullPointerException。 - equals 与 hashCode:若将自定义类作为 Set 的元素或 Map 的键,必须正确重写
equals与hashCode,否则重复判定和哈希行为会异常,参见 常用类(Object/equals-hashCode)。
相关链接
- List、Set、Map 详解与遍历 — 各接口常用方法与遍历方式(Iterator、for-each)
- 泛型在集合中的使用与常见陷阱 — 泛型与类型擦除在集合中的注意点
- Collections 工具类 — 排序、查找、不可变集合等工具方法
- 泛型基础 — 泛型类、接口、方法及类型擦除
- Oracle Java 教程 - 集合