Java 集合框架完全解析
Collection、List、Set、Map、Queue 完整对比与使用场景
集合框架结构
Iterable
└── Collection
├── List(有序、可重复)
│ ├── ArrayList
│ ├── LinkedList
│ └── Vector → Stack
│
├── Set(无序、不可重复)
│ ├── HashSet
│ ├── LinkedHashSet
│ └── TreeSet
│
└── Queue(队列)
├── Deque
│ ├── ArrayDeque
│ └── LinkedList
│
├── BlockingQueue
│ ├── ArrayBlockingQueue
│ └── LinkedBlockingQueue
│
└── PriorityQueue
└── Map(键值对)
├── HashMap
├── LinkedHashMap
├── TreeMap
├── Hashtable
└── ConcurrentHashMapCollection 接口
核心方法
java
public interface Collection<E> extends Iterable<E> {
// 基本操作
int size();
boolean isEmpty();
boolean contains(Object o);
boolean add(E e);
boolean remove(Object o);
// 批量操作
boolean addAll(Collection<? extends E> c);
boolean removeAll(Collection<?> c);
boolean retainAll(Collection<?> c);
void clear();
// 数组转换
Object[] toArray();
<T> T[] toArray(T[] a);
// 遍历
Iterator<E> iterator();
void forEach(Consumer<? super E> action);
// 批量操作(Java 8+)
boolean removeIf(Predicate<? super E> filter);
Stream<E> stream();
Stream<E> parallelStream();
}List 接口
特性
| 特性 | 说明 |
|---|---|
| 有序 | 元素按插入顺序存储 |
| 可重复 | 允许存入相同元素 |
| 有索引 | 通过下标访问(get(index)) |
| 线程不安全 | Collections.synchronizedList() 或 CopyOnWriteArrayList |
ArrayList
原理:Object[] 数组,默认容量 10,扩容 1.5 倍
java
// 初始化
List<String> list = new ArrayList<>();
List<String> list = new ArrayList<>(20); // 指定初始容量
// 添加元素
list.add("A");
list.add(0, "B"); // 插入到指定位置
// 访问
String first = list.get(0);
// 修改
list.set(0, "C");
// 删除
list.remove(0); // 按索引删除
list.remove("A"); // 按对象删除
// 遍历
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
for (String s : list) {
System.out.println(s);
}
list.forEach(System.out::println);
Iterator<String> it = list.iterator();
while (it.hasNext()) {
String s = it.next();
if (s.equals("A")) {
it.remove();
}
}特点:
| 操作 | 复杂度 |
|---|---|
| 随机访问 | O(1) |
| 尾部插入 | O(1) 均摊 |
| 中间插入/删除 | O(n) |
| 查找 | O(n) |
适用场景:需要随机访问、尾部操作多、中间操作少
LinkedList
原理:双向链表,头尾操作 O(1)
java
LinkedList<String> list = new LinkedList<>();
// 队列操作
list.offer("A"); // 队尾插入
list.poll(); // 队首取出
list.peek(); // 查看队首
// 栈操作
list.push("A"); // 压栈
list.pop(); // 弹栈
// 双端队列
list.addFirst("A");
list.addLast("B");
list.removeFirst();
list.removeLast();特点:
| 操作 | 复杂度 |
|---|---|
| 头部插入/删除 | O(1) |
| 尾部插入/删除 | O(1) |
| 随机访问 | O(n) |
| 中间插入/删除 | O(n) |
适用场景:栈/队列实现、头尾操作频繁、遍历多随机访问少
Vector / Stack
java
// Vector(同步,线程安全)
Vector<String> vector = new Vector<>();
vector.add("A");
// Stack(继承 Vector,FILO)
Stack<String> stack = new Stack<>();
stack.push("A");
stack.push("B");
stack.pop(); // B
stack.peek(); // A
stack.empty();注意:推荐用 ArrayDeque 替代 Stack,性能更好
List 对比
| 特性 | ArrayList | LinkedList | Vector |
|---|---|---|---|
| 底层结构 | 数组 | 双向链表 | 数组 |
| 线程安全 | ❌ | ❌ | ✅ |
| 扩容机制 | 1.5 倍 | 无需扩容 | 2 倍 |
| 随机访问 | O(1) | O(n) | O(1) |
| 头插入 | O(n) | O(1) | O(n) |
| 尾插入 | O(1) 均摊 | O(1) | O(1) |
| 内存占用 | 低 | 高(节点) | 低 |
| 推荐场景 | 通用场景 | 栈/队列 | 需线程安全 |
Set 接口
特性
| 特性 | 说明 |
|---|---|
| 无序 | 不保证迭代顺序(HashSet/TreeSet 可控) |
| 不可重复 | equals() 判断重复 |
| 支持泛型 | 只存一个元素 |
| 线程不安全 | Collections.synchronizedSet() 或 CopyOnWriteArraySet |
HashSet
原理:HashMap 存储元素,key 存元素,value 存 PRESENT
java
Set<String> set = new HashSet<>();
set.add("A");
set.add("B");
set.add("A"); // 添加失败,不重复
boolean contains = set.contains("A");
set.remove("A");
set.size();
set.isEmpty();
set.clear();
// 遍历
for (String s : set) {
System.out.println(s);
}
set.forEach(System.out::println);特点:
- 无序(哈希码决定顺序)
- 允许 null 元素
- 查找/添加:O(1) 均摊
- 需正确实现 hashCode() 和 equals()
LinkedHashSet
原理:HashMap + 双向链表,保持插入顺序
java
Set<String> set = new LinkedHashSet<>();
set.add("C");
set.add("A");
set.add("B");
// 迭代顺序:C -> A -> B(插入顺序)适用场景:需要保持元素插入顺序
TreeSet
原理:红黑树,按自然顺序或Comparator排序
java
// 自然顺序
Set<Integer> set = new TreeSet<>();
set.add(3);
set.add(1);
set.add(2);
// 迭代顺序:1 -> 2 -> 3
// 自定义顺序
Set<String> set = new TreeSet<>(Comparator.reverseOrder());
set.add("apple");
set.add("banana");
set.add("cherry");
// 迭代顺序:cherry -> banana -> apple
// 自定义比较器
Set<User> set = new TreeSet<>(Comparator.comparing(User::getName));特点:
| 操作 | 复杂度 |
|---|---|
| 添加 | O(log n) |
| 删除 | O(log n) |
| 查找 | O(log n) |
| 范围查找 | O(log n + k) |
适用场景:需要排序、有序遍历、范围查询
Set 对比
| 特性 | HashSet | LinkedHashSet | TreeSet |
|---|---|---|---|
| 底层结构 | HashMap | LinkedHashMap | 红黑树 |
| 迭代顺序 | 无序 | 插入顺序 | 排序顺序 |
| null 支持 | ✅ | ✅ | ❌ |
| 线程安全 | ❌ | ❌ | ❌ |
| 查找/添加 | O(1) | O(1) | O(log n) |
| 排序 | ❌ | ❌ | ✅ |
| 适用场景 | 最常用、去重 | 保持顺序 | 需要排序 |
Map 接口
核心方法
java
public interface Map<K, V> {
// 基本操作
V put(K key, V value);
V get(Object key);
V remove(Object key);
boolean containsKey(Object key);
boolean containsValue(Object value);
int size();
boolean isEmpty();
void clear();
// 批量操作
void putAll(Map<? extends K, ? extends V> m);
// 视图
Set<K> keySet();
Collection<V> values();
Set<Map.Entry<K, V>> entrySet();
// Entry
interface Entry<K, V> {
K getKey();
V getValue();
V setValue(V value);
}
// Java 8+
V getOrDefault(Object key, V defaultValue);
V putIfAbsent(K key, V value);
boolean remove(Object key, Object value);
boolean replace(K key, V oldValue, V newValue);
V replace(K key, V value);
void replaceAll(BiFunction<? super K, ? super V, ? extends V> function);
void forEach(BiConsumer<? super K, ? super V> action);
merge(K key, V value, BiFunction<V, V, V> remappingFunction);
compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction);
computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction);
computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction);
}HashMap
原理:数组 + 链表/红黑树( JDK 1.8+ ),链表超过 8 转为红黑树
java
Map<String, Integer> map = new HashMap<>();
// 添加
map.put("A", 1);
map.put("B", 2);
map.put("C", 3);
// 获取
Integer value = map.get("A");
Integer defaultVal = map.getOrDefault("D", 0); // 0
// 修改
map.put("A", 10); // 覆盖
map.replace("B", 20); // 返回旧值
// 删除
map.remove("A");
map.remove("B", 2); // key 和 value 都匹配才删除
// 判断
boolean hasA = map.containsKey("A");
boolean hasOne = map.containsValue(1);
// 遍历
for (Map.Entry<String, Integer> entry : map.entrySet()) {
System.out.println(entry.getKey() + " = " + entry.getValue());
}
for (String key : map.keySet()) {
System.out.println(key);
}
for (Integer value : map.values()) {
System.out.println(value);
}
map.forEach((k, v) -> System.out.println(k + " = " + v));特点:
| 操作 | 复杂度 |
|---|---|
| get/put | O(1) 均摊 |
| 最坏情况 | O(n)(大量哈希冲突) |
| 容量 | 2^n,自动扩容 |
| 初始容量 | 16,负载因子 0.75 |
LinkedHashMap
原理:HashMap + 双向链表,保持访问/插入顺序
java
Map<String, Integer> map = new LinkedHashMap<>();
map.put("C", 3);
map.put("A", 1);
map.put("B", 2);
// 迭代顺序:C -> A -> B
// 访问顺序(LRU 缓存)
Map<String, Integer> lru = new LinkedHashMap<>(16, 0.75f, true);
lru.put("A", 1);
lru.put("B", 2);
lru.get("A"); // 访问后顺序变为:B -> ATreeMap
原理:红黑树,按 key 排序
java
Map<String, Integer> map = new TreeMap<>();
map.put("c", 3);
map.put("a", 1);
map.put("b", 2);
// 迭代顺序:a -> b -> c(字典序)
// 自定义排序
Map<String, Integer> map = new TreeMap<>(Comparator.reverseOrder());
// 导航方法
map.ceilingKey("B"); // >= "B" 的最小 key
map.floorKey("B"); // <= "B" 的最大 key
map.higherKey("B"); // > "B" 的最小 key
map.lowerKey("B"); // < "B" 的最大 key
map.firstEntry(); // 最小 entry
map.lastEntry(); // 最大 entryHashtable
原理:早期实现,线程安全( synchronized ),不允许 null
java
Map<String, Integer> map = new Hashtable<>();
map.put("A", 1);
map.get("A");
map.remove("A");注意:已过时,推荐用 ConcurrentHashMap
Map 对比
| 特性 | HashMap | LinkedHashMap | TreeMap | Hashtable |
|---|---|---|---|---|
| 底层结构 | 数组+链表/红黑树 | HashMap+链表 | 红黑树 | 数组+链表 |
| 迭代顺序 | 无序 | 插入/访问顺序 | 排序顺序 | 无序 |
| null key | ✅ | ✅ | ❌ | ❌ |
| null value | ✅ | ✅ | ✅ | ❌ |
| 线程安全 | ❌ | ❌ | ❌ | ✅ |
| 查找/添加 | O(1) | O(1) | O(log n) | O(1) |
| 排序 | ❌ | ❌ | ✅ | ❌ |
| 适用场景 | 最常用 | 保持顺序 | 需要排序 | 需线程安全 |
Queue 接口
核心方法
java
public interface Queue<E> extends Collection<E> {
// 添加(队列满时抛异常)
void add(E e);
// 添加(队列满时返回 false)
boolean offer(E e);
// 移除(队列空时抛异常)
E remove();
// 移除(队列空时返回 null)
E poll();
// 查看(队列空时抛异常)
E element();
// 查看(队列空时返回 null)
E peek();
}Deque 接口
java
public interface Deque<E> extends Queue<E> {
// 两端操作
void addFirst(E e);
void addLast(E e);
boolean offerFirst(E e);
boolean offerLast(E e);
E removeFirst();
E removeLast();
E pollFirst();
E pollLast();
E getFirst();
E getLast();
E peekFirst();
E peekLast();
// 栈操作
void push(E e); // = addFirst
E pop(); // = removeFirst
}实现类对比
| 实现类 | 底层 | null | 线程安全 | 特点 |
|---|---|---|---|---|
| ArrayDeque | 数组 | ❌ | ❌ | 栈/队列首选,性能好 |
| LinkedList | 链表 | ✅ | ❌ | 可做 List/Deque |
| PriorityQueue | 堆 | ❌ | ❌ | 按优先级排序 |
| ArrayBlockingQueue | 数组 | ❌ | ✅ | 有界队列 |
| LinkedBlockingQueue | 链表 | ✅ | ✅ | 可选有界/无界 |
ArrayDeque
java
Deque<String> deque = new ArrayDeque<>();
// 队列操作
deque.offer("A"); // 队尾
deque.offer("B");
deque.poll(); // 队首:A
// 栈操作
deque.push("X"); // 栈顶
deque.push("Y");
deque.pop(); // Y
// 双端操作
deque.addFirst("F");
deque.addLast("L");
deque.removeFirst();
deque.removeLast();PriorityQueue
java
// 最小堆(默认)
PriorityQueue<Integer> minHeap = new PriorityQueue<>();
minHeap.add(5);
minHeap.add(2);
minHeap.add(8);
minHeap.poll(); // 2
// 最大堆
PriorityQueue<Integer> maxHeap = new PriorityQueue<>(Comparator.reverseOrder());
// 自定义比较器
PriorityQueue<User> users = new PriorityQueue<>(
Comparator.comparingInt(User::getAge).reversed()
);线程安全集合
对比
| 线程安全实现 | 适用场景 |
|---|---|
| Collections.synchronizedList/Set/Map | 简单场景,性能要求不高 |
| CopyOnWriteArrayList | 读多写少 |
| CopyOnWriteArraySet | 读多写少,元素少 |
| ConcurrentHashMap | 高并发读写的 Map |
| ConcurrentLinkedQueue | 高并发无界队列 |
| BlockingQueue | 生产者-消费者模式 |
| ConcurrentSkipListMap/Set | 需要排序的高并发 |
ConcurrentHashMap
java
ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
// 基本操作
map.put("A", 1);
map.get("A");
// 原子操作
map.putIfAbsent("A", 1); // key 不存在才插入
map.remove("A", 1); // key-value 都匹配才删除
map.replace("A", 1, 10); // key-oldValue 匹配才替换
// 批量操作
map.putAll(anotherMap);
// 遍历(弱一致性)
map.forEach((k, v) -> {});
map.entrySet().forEach(e -> {});
// 计数
map.mappingCount(); // 返回 long
// 搜索
map.search(1, (k, v) -> v > 10 ? k : null);BlockingQueue
java
BlockingQueue<String> queue = new ArrayBlockingQueue<>(10);
// 生产者
queue.put("A"); // 队列满则阻塞
queue.offer("A", 1, TimeUnit.SECONDS); // 超时放弃
// 消费者
String item = queue.take(); // 队列空则阻塞
String item = queue.poll(1, TimeUnit.SECONDS); // 超时返回 null实现类:
| 类 | 特点 |
|---|---|
| ArrayBlockingQueue | 有界,数组 |
| LinkedBlockingQueue | 可选有界/无界,链表 |
| SynchronousQueue | 不存储元素,必须同步交接 |
| PriorityBlockingQueue | 无界,按优先级 |
| DelayQueue | 无界,延迟元素 |
集合工具类
Collections
java
// 排序
List<Integer> list = new ArrayList<>();
Collections.sort(list);
Collections.sort(list, Comparator.reverseOrder());
// 逆序
Collections.reverse(list);
// 混排(洗牌)
Collections.shuffle(list);
// 查找
int index = Collections.binarySearch(sortedList, target);
// 极值
Collections.max(collection);
Collections.min(collection);
// 同步控制
List<String> syncList = Collections.synchronizedList(new ArrayList<>());
Set<String> syncSet = Collections.synchronizedSet(new HashSet<>());
Map<String, Integer> syncMap = Collections.synchronizedMap(new HashMap<>());
// 不可变集合
List<String> immutable = Collections.unmodifiableList(list);
Set<String> immutableSet = Collections.unmodifiableSet(set);
Map<String, Integer> immutableMap = Collections.unmodifiableMap(map);
// 单一元素集合
Set<String> singleton = Collections.singleton("only");
List<String> singletonList = Collections.singletonList("only");
Map<String, Integer> singletonMap = Collections.singletonMap("key", 1);
// 空集合
Collections.emptyList();
Collections.emptySet();
Collections.emptyMap();Arrays
java
// 数组转 List
String[] arr = {"A", "B", "C"};
List<String> list = Arrays.asList(arr);
List<String> list = Arrays.asList("A", "B", "C");
// List 转数组
String[] arr = list.toArray(new String[0]);
String[] arr = list.toArray(String[]::new);
// 数组排序
int[] nums = {3, 1, 2};
Arrays.sort(nums);
Arrays.sort(nums, Comparator.reverseOrder());
// 数组填充
Arrays.fill(arr, 0);
// 数组二分查找
int index = Arrays.binarySearch(sortedArr, target);
// 数组比较
boolean equal = Arrays.equals(arr1, arr2);
// 数组转字符串
String str = Arrays.toString(arr);
// 创建空数组
String[] empty = Arrays.emptyArray();
// 构造数组的流
Arrays.stream(nums).sum();最佳实践
选择合适的集合
| 场景 | 推荐 |
|---|---|
| 需要快速查找 | HashMap / HashSet |
| 需要保持顺序 | LinkedHashMap / LinkedHashSet |
| 需要按键排序 | TreeMap / TreeSet |
| 需要频繁头尾操作 | ArrayDeque / LinkedList |
| 需要按优先级 | PriorityQueue |
| 高并发读写 | ConcurrentHashMap |
| 读多写少 | CopyOnWriteArrayList |
性能优化
java
// 指定初始容量,避免扩容
new ArrayList<>(expectedSize);
new HashMap<>(expectedSize);
// 使用接口编程
List<String> list = new ArrayList<>(); // 面向接口
Set<String> set = new HashSet<>();
// 选择合适的实现
// ArrayList vs LinkedList
// 尾插多用 ArrayList
// 头插多用 LinkedList
// 避免使用包装类型做 key
// 用 String / Integer 代替自定义对象常见错误
java
// ❌ 错误:数组转型
List<Object> list = new ArrayList<String>(); // 编译错误
// ❌ 错误:在遍历中删除
for (String s : list) {
list.remove(s); // ConcurrentModificationException
}
// ✅ 正确:迭代器删除
Iterator<String> it = list.iterator();
while (it.hasNext()) {
if (condition) {
it.remove();
}
}
// ✅ 正确:removeIf
list.removeIf(s -> condition);
// ❌ 错误:可变对象做 key
Map<List<String>, Integer> map; // 不推荐,list 内容变化后哈希失效
// ✅ 正确:使用不可变对象
Map<String, Integer> map;相关页面
- **Java\Java_base\Java基础-完全指南** - 返回总览
- **Java\Java_advanced\Stream流收集数据与Lambda详解** - Stream API
- **Java\Java_advanced\Java多线程编程** - 并发集合
#标签 #java #集合 #collection #list #set #map #queue #数据结构