一、Java 容器体系
1.1 核心分类
Collection(单列元素存储)List(有序、可重复):ArrayList、LinkedList、Vector、StackSet(无序、不可重复):HashSet、LinkedHashSet、TreeSetMap(双列键值对存储):HashMap、LinkedHashMap、TreeMap、ConcurrentHashMap、Hashtable
二、核心概念辨析
2.1 Collection 和 Collections
Collection 作为接口,定义了 List、Set 等单列集合的通用方法(add、remove、size 等),是这类集合的父接口;Collections 作为工具类,提供排序、查找、线程安全包装等静态方法,辅助操作 Collection 容器。
2.2 List、Set、Map 核心区别
表格
| 容器类型 | 元素是否有序 | 元素是否可重复 | 核心特点 |
|---|---|---|---|
| List | 按插入顺序有序 | 可重复 | 支持索引快速访问 |
| Set | HashSet 无序、LinkedHashSet 按插入序、TreeSet 按自然序 | 不可重复 | 基于哈希 / 红黑树去重,无索引 |
| Map | HashMap 无序、LinkedHashMap 按插入序、TreeMap 按 key 排序 | key 不可重复,value 可重复 | 基于 key 快速查找 value,无索引 |
注意:Map 未继承 Collection 接口,是独立的顶级接口。
三、常用容器实现与实践
3.1 List 实现类对比
ArrayList 基于动态数组,查询快(O (1))、中间增删慢(O (n)),非线程安全,默认初始容量 10,扩容时增加 50%;LinkedList 基于双向链表,查询慢(O (n))、增删快(O (1)),非线程安全;Vector 基于动态数组,线程安全(方法加 synchronized),性能低于 ArrayList,扩容默认翻倍。
性能对比示例:
java
运行
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class ListPerformanceTest {
public static void main(String[] args) {
int size = 100000;
List<Integer> arrayList = new ArrayList<>();
List<Integer> linkedList = new LinkedList<>();
// 尾部添加
long start = System.currentTimeMillis();
for (int i = 0; i < size; i++) arrayList.add(i);
System.out.println("ArrayList尾部添加耗时:" + (System.currentTimeMillis() - start) + "ms");
start = System.currentTimeMillis();
for (int i = 0; i < size; i++) linkedList.add(i);
System.out.println("LinkedList尾部添加耗时:" + (System.currentTimeMillis() - start) + "ms");
// 随机访问
start = System.currentTimeMillis();
for (int i = 0; i < size; i++) arrayList.get(i);
System.out.println("ArrayList随机访问耗时:" + (System.currentTimeMillis() - start) + "ms");
start = System.currentTimeMillis();
for (int i = 0; i < size; i++) linkedList.get(i);
System.out.println("LinkedList随机访问耗时:" + (System.currentTimeMillis() - start) + "ms");
}
}
运行结果体现:ArrayList 随机访问远快于 LinkedList,尾部添加二者效率接近。
3.2 Set 实现类对比
HashSet 底层依赖 HashMap,元素存于 key 位置,value 为固定空对象,无序、查询快(O (1)),允许一个 null 元素;TreeSet 基于红黑树,按元素自然序 / 自定义规则排序,查询复杂度 O (logn),不允许 null。
使用示例:
java
运行
import java.util.HashSet;
import java.util.TreeSet;
public class SetDemo {
public static void main(String[] args) {
HashSet<String> hashSet = new HashSet<>();
hashSet.add("apple");
hashSet.add("apple"); // 重复元素不添加
System.out.println("HashSet:" + hashSet);
TreeSet<Integer> treeSet = new TreeSet<>((a, b) -> b - a); // 自定义降序
treeSet.add(5);
treeSet.add(2);
System.out.println("TreeSet降序:" + treeSet);
}
}
3.3 Map 实现类对比
表格
| 特性 | HashMap | Hashtable | ConcurrentHashMap |
|---|---|---|---|
| 线程安全 | 非线程安全 | 方法加 synchronized,线程安全 | 分段锁 / CAS 实现,线程安全且效率更高 |
| null 支持 | key/value 均可为 null | 均不允许 null | 均不允许 null |
| 初始容量 / 扩容 | 初始 16,扩容 2 倍 | 初始 11,扩容 2 倍 + 1 | 初始 16,扩容 2 倍 |
HashMap 使用示例:
java
运行
import java.util.HashMap;
import java.util.Map;
public class HashMapDemo {
public static void main(String[] args) {
Map<String, String> hashMap = new HashMap<>();
hashMap.put("name", "菜菜");
hashMap.put(null, "nullKey"); // 支持null key
// 推荐entrySet遍历
for (Map.Entry<String, String> entry : hashMap.entrySet()) {
System.out.println(entry.getKey() + ":" + entry.getValue());
}
}
}
四、高频问题
4.1 Iterator 与 ListIterator
Iterator 可遍历 Set/List,仅单向遍历,支持移除元素;ListIterator 仅遍历 List,支持双向遍历,可添加、替换元素,获取索引。
4.2 不可变集合
通过 Collections.unmodifiableXXX 创建只读集合,修改会抛出 UnsupportedOperationException:
java
运行
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class UnmodifiableDemo {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("Java");
List<String> unmodifiableList = Collections.unmodifiableList(list);
try {
unmodifiableList.add("Python"); // 抛出异常
} catch (Exception e) {
System.out.println("不可变集合禁止修改");
}
}
}
4.3 Queue 中 poll () 与 remove ()
poll () 移除队头元素,队空返回 null;remove () 移除队头元素,队空抛出 NoSuchElementException。
五、使用
频繁查询选 ArrayList,频繁增删选 LinkedList;无需排序选 HashMap/HashSet,需排序选 TreeMap/TreeSet;多线程用 ConcurrentHashMap。初始化优化:给 ArrayList、HashMap 指定初始容量,减少扩容损耗。遍历优化:Map 遍历优先用 entrySet (),减少哈希计算。空指针规避:HashMap.get () 结果判空,Hashtable/ConcurrentHashMap 使用前校验 null。