外观
Java 集合框架精要
约 2149 字大约 7 分钟
2025-08-16
一、集合框架概述
1.1 集合与数组的比较
| 特性 | 数组 | 集合 |
|---|---|---|
| 大小 | 固定 | 可变 |
| 类型 | 可存储基本数据类型 | 只能存储对象(基本类型需用包装类) |
| 类型一致性 | 只能存放同一种类型 | 可以存放不同类型的对象(不推荐) |
| 功能 | 功能简单 | 功能丰富,提供多种操作方法 |
1.2 集合框架主要接口
Java集合框架主要分为三大类:
- List:有序、可重复的集合
- Set:无序、不可重复的集合
- Map:键值对映射集合

二、List 接口
2.1 ArrayList(最常用)
特点:
- 基于动态数组实现,查询快,增删慢
- 随机访问性能好(通过索引访问元素)
- 默认初始容量为10,扩容机制为原容量的1.5倍
import java.util.ArrayList;
import java.util.List;
public class ArrayListDemo {
public static void main(String[] args) {
// 创建ArrayList
List<String> list = new ArrayList<>();
// 添加元素
list.add("Java");
list.add("Python");
list.add("C++");
// 插入元素(指定位置)
list.add(1, "JavaScript");
// 访问元素
System.out.println(list.get(0)); // 输出: Java
// 修改元素
list.set(2, "C#");
// 删除元素
list.remove(0); // 按索引删除
list.remove("C#"); // 按对象删除
// 遍历
for (String item : list) {
System.out.println(item);
}
// 转换为数组
String[] array = list.toArray(new String[0]);
}
}常用方法:
add(E e):添加元素add(int index, E element):在指定位置插入元素get(int index):获取指定位置的元素set(int index, E element):替换指定位置的元素remove(int index):删除指定位置的元素size():获取集合大小contains(Object o):检查是否包含某元素indexOf(Object o):查找元素首次出现的位置clear():清空集合
2.2 LinkedList
特点:
- 基于双向链表实现,增删快,查询慢
- 既可作为列表使用,也可作为队列或栈使用
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.Deque;
public class LinkedListDemo {
public static void main(String[] args) {
// 作为List使用
List<String> list = new LinkedList<>();
list.add("Java");
list.add("Python");
// 作为Queue使用(先进先出)
Queue<String> queue = new LinkedList<>();
queue.offer("Task1"); // 添加元素
queue.offer("Task2");
System.out.println(queue.poll()); // 输出: Task1
// 作为Deque使用(双端队列)
Deque<String> deque = new LinkedList<>();
deque.addFirst("Front");
deque.addLast("Back");
System.out.println(deque.removeFirst()); // 输出: Front
System.out.println(deque.removeLast()); // 输出: Back
}
}三、Set 接口
3.1 HashSet(最常用)
特点:
- 基于哈希表实现
- 无序、不重复
- 允许一个null元素
- 添加、删除、查找操作的时间复杂度接近O(1)
import java.util.HashSet;
import java.util.Set;
public class HashSetDemo {
public static void main(String[] args) {
Set<String> set = new HashSet<>();
// 添加元素
set.add("Java");
set.add("Python");
set.add("C++");
// 重复元素不会被添加
boolean added = set.add("Java"); // 返回false
// 遍历
for (String item : set) {
System.out.println(item);
}
// 检查元素是否存在
boolean contains = set.contains("Python"); // true
// 删除元素
set.remove("C++");
// 获取集合大小
int size = set.size();
}
}3.2 LinkedHashSet
特点:
- 继承自HashSet
- 维护插入顺序
- 底层使用双向链表维护元素顺序
import java.util.LinkedHashSet;
import java.util.Set;
public class LinkedHashSetDemo {
public static void main(String[] args) {
Set<String> set = new LinkedHashSet<>();
set.add("A");
set.add("0");
set.add("-");
set.add("+");
// 按插入顺序遍历
for (String item : set) {
System.out.println(item); // 输出顺序与插入顺序一致
}
}
}四、Map 接口
4.1 HashMap(最常用)
特点:
- 基于哈希表实现
- 键值对存储,键不允许重复
- 无序
- 允许一个null键和多个null值
import java.util.HashMap;
import java.util.Map;
public class HashMapDemo {
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<>();
// 添加键值对
map.put("Java", 1);
map.put("Python", 2);
map.put("C++", 3);
// 重复键会覆盖旧值
map.put("C++", 4); // C++的值变为4
// 检查键是否存在
boolean containsKey = map.containsKey("Java"); // true
// 检查值是否存在
boolean containsValue = map.containsValue(2); // true
// 获取值
Integer value = map.get("Python"); // 2
// 遍历方式1:遍历键
for (String key : map.keySet()) {
System.out.println(key + ": " + map.get(key));
}
// 遍历方式2:遍历键值对
for (Map.Entry<String, Integer> entry : map.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
// 遍历方式3:Java 8+ forEach
map.forEach((key, value) -> System.out.println(key + ": " + value));
// 删除键值对
map.remove("C++");
}
}常用方法:
put(K key, V value):添加键值对get(Object key):获取键对应的值containsKey(Object key):检查是否包含指定键containsValue(Object value):检查是否包含指定值remove(Object key):删除指定键的映射keySet():获取所有键的集合values():获取所有值的集合entrySet():获取所有键值对的集合size():获取映射数量isEmpty():检查是否为空
4.2 LinkedHashMap
特点:
- 继承自HashMap
- 维护插入顺序或访问顺序
- 底层使用双向链表维护元素顺序
import java.util.LinkedHashMap;
import java.util.Map;
public class LinkedHashMapDemo {
public static void main(String[] args) {
// 按插入顺序维护
Map<String, Integer> map = new LinkedHashMap<>();
map.put("A", 1);
map.put("0", 2);
map.put("-", 3);
map.put("+", 4);
// 按插入顺序遍历
map.forEach((key, value) -> System.out.println(key + ": " + value));
}
}五、集合工具类
5.1 Collections 工具类
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class CollectionsDemo {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(3);
list.add(1);
list.add(2);
// 排序
Collections.sort(list); // [1, 2, 3]
// 查找最大值/最小值
int max = Collections.max(list); // 3
int min = Collections.min(list); // 1
// 二分查找(必须先排序)
int index = Collections.binarySearch(list, 2); // 1
// 反转列表
Collections.reverse(list); // [3, 2, 1]
// 填充(覆盖已有元素)
Collections.fill(list, 0); // [0, 0, 0]
// 创建不可修改的集合
List<Integer> unmodifiableList = Collections.unmodifiableList(list);
// unmodifiableList.add(10); // 会抛出UnsupportedOperationException
// 创建空集合
List<String> emptyList = Collections.emptyList();
// 创建单元素集合
List<String> singletonList = Collections.singletonList("Java");
}
}5.2 Arrays 工具类
import java.util.Arrays;
import java.util.List;
public class ArraysDemo {
public static void main(String[] args) {
// 数组转List(注意:返回的是固定大小的List,不可修改)
String[] array = {"Java", "Python", "C++"};
List<String> list = Arrays.asList(array);
// 创建可修改的List
List<String> modifiableList = new ArrayList<>(Arrays.asList(array));
// 排序
int[] numbers = {3, 1, 2};
Arrays.sort(numbers); // [1, 2, 3]
// 填充
Arrays.fill(numbers, 0); // [0, 0, 0]
// 比较
boolean isEqual = Arrays.equals(new int[]{1, 2, 3}, new int[]{1, 2, 3}); // true
// 转换为字符串
String str = Arrays.toString(numbers); // "[0, 0, 0]"
}
}六、Stream API(Java 8+)
6.1 基本概念
Stream API提供了一种声明式处理数据的方式,可以极大提高代码的可读性和简洁性。
6.2 常用操作
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class StreamDemo {
public static void main(String[] args) {
List<String> list = Arrays.asList("Java", "Python", "C++", "JavaScript", "Ruby");
// 过滤:筛选长度大于4的字符串
List<String> filtered = list.stream()
.filter(s -> s.length() > 4)
.collect(Collectors.toList()); // [Python, JavaScript]
// 映射:转换为大写
List<String> upperCase = list.stream()
.map(String::toUpperCase)
.collect(Collectors.toList()); // [JAVA, PYTHON, C++, JAVASCRIPT, RUBY]
// 排序:按字母顺序排序
List<String> sorted = list.stream()
.sorted()
.collect(Collectors.toList()); // [C++, Java, JavaScript, Python, Ruby]
// 限制:取前2个元素
List<String> limited = list.stream()
.limit(2)
.collect(Collectors.toList()); // [Java, Python]
// 跳过:跳过前2个元素
List<String> skipped = list.stream()
.skip(2)
.collect(Collectors.toList()); // [C++, JavaScript, Ruby]
// 去重
List<String> distinct = Arrays.asList("A", "B", "A", "C").stream()
.distinct()
.collect(Collectors.toList()); // [A, B, C]
// 匹配:检查是否有以"J"开头的元素
boolean anyMatch = list.stream().anyMatch(s -> s.startsWith("J")); // true
boolean allMatch = list.stream().allMatch(s -> s.length() > 1); // true
boolean noneMatch = list.stream().noneMatch(s -> s.startsWith("Z")); // true
// 归约:计算所有字符串长度之和
int sumLength = list.stream()
.map(String::length)
.reduce(0, Integer::sum); // 24
// 收集:按字符串长度分组
Map<Integer, List<String>> grouped = list.stream()
.collect(Collectors.groupingBy(String::length));
// {2=[C++], 4=[Java, Ruby], 6=[Python], 10=[JavaScript]}
// forEach:遍历
list.stream().forEach(System.out::println);
}
}6.3 Stream 操作类型
- 中间操作:返回Stream对象,可链式调用(如filter, map, sorted, distinct等)
- 终端操作:返回最终结果或副作用(如collect, forEach, reduce, count等)
七、最佳实践
7.1 选择合适的集合类型
- List:
- 需要频繁随机访问 → ArrayList
- 需要频繁在中间插入/删除 → LinkedList
- Set:
- 无序且不需要维护顺序 → HashSet
- 需要维护插入顺序 → LinkedHashSet
- Map:
- 无序且不需要维护顺序 → HashMap
- 需要维护插入顺序 → LinkedHashMap
7.2 使用泛型
始终使用泛型来提高类型安全性和代码可读性:
// 推荐
List<String> list = new ArrayList<>();
// 不推荐(原始类型)
List list = new ArrayList();7.3 初始化容量
对于已知大致元素数量的集合,初始化时指定容量可提高性能:
// 已知将添加1000个元素
List<String> list = new ArrayList<>(1000);7.4 避免在循环中修改集合
在遍历集合时修改集合可能导致ConcurrentModificationException:
// 错误示例
List<String> list = new ArrayList<>(Arrays.asList("A", "B", "C"));
for (String item : list) {
if ("B".equals(item)) {
list.remove(item); // 会抛出ConcurrentModificationException
}
}
// 正确做法1:使用迭代器
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
if ("B".equals(iterator.next())) {
iterator.remove();
}
}
// 正确做法2:使用removeIf(Java 8+)
list.removeIf(item -> "B".equals(item));7.5 使用不可变集合
当集合不应被修改时,使用不可变集合提高安全性:
// Java 9+ 创建不可变集合
List<String> immutableList = List.of("Java", "Python", "C++");
Map<String, Integer> immutableMap = Map.of("Java", 1, "Python", 2);
// Java 8 使用Collections
List<String> oldStyle = Collections.unmodifiableList(new ArrayList<>(Arrays.asList("Java", "Python")));