Java集合框架(Java Collections Framework)是Java语言中用于存储和操作数据集合的一套标准化架构。这个框架从JDK 1.2版本开始引入,经过20多年的发展已经成为Java开发中最基础、使用最频繁的组件之一。
集合框架的核心设计理念是提供一组高性能、可扩展的接口和实现类,让开发者能够以统一的方式处理各种数据结构。与直接使用数组相比,集合框架提供了更丰富的操作方法和更灵活的数据组织方式。
在实际开发中,约80%的业务代码都会涉及到集合类的使用,熟练掌握集合框架是Java开发者的基本功。
Collection是集合框架的根接口,定义了所有集合类型共有的基本操作:
java复制public interface Collection<E> extends Iterable<E> {
// 基本操作
int size();
boolean isEmpty();
boolean contains(Object o);
Iterator<E> iterator();
Object[] toArray();
<T> T[] toArray(T[] a);
// 修改操作
boolean add(E e);
boolean remove(Object o);
// 批量操作
boolean containsAll(Collection<?> c);
boolean addAll(Collection<? extends E> c);
boolean removeAll(Collection<?> c);
boolean retainAll(Collection<?> c);
void clear();
// 比较和哈希
boolean equals(Object o);
int hashCode();
}
Collection接口的主要特点:
List代表有序集合(序列),特点包括:
java复制public interface List<E> extends Collection<E> {
// 位置访问操作
E get(int index);
E set(int index, E element);
void add(int index, E element);
E remove(int index);
int indexOf(Object o);
int lastIndexOf(Object o);
// 列表迭代器
ListIterator<E> listIterator();
ListIterator<E> listIterator(int index);
// 范围视图
List<E> subList(int fromIndex, int toIndex);
}
List的典型实现类:
Set代表不允许重复元素的集合,主要特点:
java复制public interface Set<E> extends Collection<E> {
// 从Collection继承的方法
// 特别强调不允许重复元素
}
Set的典型实现类:
Queue表示队列这种先进先出(FIFO)的数据结构:
java复制public interface Queue<E> extends Collection<E> {
// 插入操作
boolean add(E e);
boolean offer(E e);
// 移除操作
E remove();
E poll();
// 检查操作
E element();
E peek();
}
Queue的主要实现类:
虽然Map不是Collection的子接口,但它是集合框架的重要组成部分:
java复制public interface Map<K,V> {
// 基本操作
int size();
boolean isEmpty();
boolean containsKey(Object key);
boolean containsValue(Object value);
V get(Object key);
V put(K key, V value);
V remove(Object key);
// 批量操作
void putAll(Map<? extends K, ? extends V> m);
void clear();
// 集合视图
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);
}
}
Map的主要实现类:
Java集合框架的接口继承体系如下:
code复制Iterable
└── Collection
├── List
├── Set
└── Queue
Map(独立接口)
选择集合类时应考虑以下因素:
元素唯一性要求:
元素顺序要求:
性能考量:
线程安全需求:
| 集合类型 | 获取 | 插入 | 删除 | 包含 | 顺序 |
|---|---|---|---|---|---|
| ArrayList | O(1) | O(1) | O(n) | O(n) | 插入顺序 |
| LinkedList | O(n) | O(1) | O(1) | O(n) | 插入顺序 |
| HashSet | O(1) | O(1) | O(1) | O(1) | 无 |
| TreeSet | O(log n) | O(log n) | O(log n) | O(log n) | 排序顺序 |
| HashMap | O(1) | O(1) | O(1) | O(1) | 无 |
| TreeMap | O(log n) | O(log n) | O(log n) | O(log n) | 键排序 |
从Java 9开始,可以使用of()方法创建不可变集合:
java复制List<String> immutableList = List.of("a", "b", "c");
Set<Integer> immutableSet = Set.of(1, 2, 3);
Map<String, Integer> immutableMap = Map.of("a", 1, "b", 2);
不可变集合的特点:
Collections类提供了大量实用方法:
java复制// 排序
Collections.sort(list);
// 创建同步集合
List<String> syncList = Collections.synchronizedList(new ArrayList<>());
// 不可变视图
List<String> unmodifiable = Collections.unmodifiableList(list);
// 其他实用方法
Collections.reverse(list);
Collections.shuffle(list);
Collections.binarySearch(list, key);
正确的泛型使用方式:
java复制// 好的实践:明确指定泛型类型
List<String> names = new ArrayList<>();
names.add("Alice"); // 编译时类型检查
// 避免使用原生类型
List rawList = new ArrayList(); // 不推荐
rawList.add("Bob");
rawList.add(123); // 运行时可能出错
对于已知大小的集合,设置初始容量可提高性能:
java复制// ArrayList默认初始容量10
List<String> list = new ArrayList<>(1000); // 避免多次扩容
// HashMap默认初始容量16,负载因子0.75
Map<String, Integer> map = new HashMap<>(64, 0.8f);
对于会增长的大型集合,设置合理的初始容量可以减少数组扩容带来的性能损耗。
问题现象:
java复制List<String> list = new ArrayList<>(Arrays.asList("a", "b", "c"));
for (String s : list) {
if (s.equals("b")) {
list.remove(s); // 抛出ConcurrentModificationException
}
}
解决方案:
对象在集合中的行为依赖于equals()和hashCode()方法:
java复制class Person {
String name;
int age;
@Override
public boolean equals(Object o) {
// 实现细节...
}
@Override
public int hashCode() {
// 必须与equals()保持一致
}
}
重要规则:
避免频繁的装箱拆箱:
java复制// 不好的做法
List<Integer> list = new ArrayList<>();
for (int i = 0; i < 10000; i++) {
list.add(i); // 自动装箱
}
// 更好的选择(特定场景)
IntStream.range(0, 10000).boxed().collect(Collectors.toList());
选择合适的集合类型:
使用批量操作:
java复制// 优于逐个添加
list.addAll(otherList);
// 批量删除
list.removeAll(toRemove);
集合与Stream的转换:
java复制List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
// 集合转Stream
long count = names.stream()
.filter(name -> name.length() > 4)
.count();
// Stream转集合
List<String> longNames = names.stream()
.filter(name -> name.length() > 4)
.collect(Collectors.toList());
Java 9引入的简洁创建方式:
java复制List<String> list = List.of("a", "b", "c");
Set<Integer> set = Set.of(1, 2, 3);
Map<String, Integer> map = Map.of("a", 1, "b", 2);
// 超过10个元素
Map<String, Integer> bigMap = Map.ofEntries(
Map.entry("a", 1),
Map.entry("b", 2),
// ...
);
Java 8为Map添加的新方法:
java复制Map<String, Integer> map = new HashMap<>();
// 键不存在时计算值
map.computeIfAbsent("key", k -> calculateValue(k));
// 合并值
map.merge("key", 1, Integer::sum);
// 遍历
map.forEach((k, v) -> System.out.println(k + ": " + v));
使用LinkedHashMap实现LRU缓存:
java复制class LRUCache<K, V> extends LinkedHashMap<K, V> {
private final int maxSize;
public LRUCache(int maxSize) {
super(maxSize, 0.75f, true);
this.maxSize = maxSize;
}
@Override
protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
return size() > maxSize;
}
}
// 使用示例
LRUCache<String, Object> cache = new LRUCache<>(100);
cache.put("key1", value1);
Object value = cache.get("key1");
使用Map进行词频统计:
java复制List<String> words = Arrays.asList("apple", "banana", "apple", "orange", "banana", "apple");
Map<String, Integer> frequency = new HashMap<>();
for (String word : words) {
frequency.merge(word, 1, Integer::sum);
}
// Java 8方式
Map<String, Long> freq = words.stream()
.collect(Collectors.groupingBy(
Function.identity(),
Collectors.counting()
));
使用Map保存多个值:
java复制Map<String, List<String>> multiMap = new HashMap<>();
// 添加值
multiMap.computeIfAbsent("key", k -> new ArrayList<>()).add("value1");
multiMap.computeIfAbsent("key", k -> new ArrayList<>()).add("value2");
// Java 8方式
List<String> values = multiMap.getOrDefault("key", Collections.emptyList());
集合框架的核心设计原则:
java复制// 好的实践
List<String> list = new ArrayList<>();
// 需要时更换实现
list = new LinkedList<>();
集合框架使用迭代器提供统一的遍历方式:
java复制// 传统方式
Iterator<String> it = list.iterator();
while (it.hasNext()) {
String item = it.next();
// 处理item
}
// for-each循环(语法糖)
for (String item : list) {
// 处理item
}
处理集合参数时的注意事项:
java复制public void processNames(List<String> names) {
// 防御性复制
List<String> copy = new ArrayList<>(names);
// 处理copy而不是原始集合
}
集合与数组之间的转换:
java复制// 集合转数组
String[] array = list.toArray(new String[0]);
// 数组转集合(返回的List是不可变的)
List<String> list = Arrays.asList(array);
// Java 8方式(可变集合)
List<String> mutableList = new ArrayList<>(Arrays.asList(array));
ArrayList扩容策略:
HashMap扩容策略:
常见集合的内存特点:
与集合相关的JVM参数:
-XX:+UseCompressedOops:压缩指针(默认开启)-Xms和-Xmx:堆内存大小-XX:+PrintGCDetails:监控GC行为实现自己的集合类示例:
java复制class CaseInsensitiveSet implements Set<String> {
private final Set<String> delegate = new HashSet<>();
@Override
public boolean add(String s) {
return delegate.add(s.toLowerCase());
}
@Override
public boolean contains(Object o) {
return o instanceof String &&
delegate.contains(((String) o).toLowerCase());
}
// 实现其他方法...
}
通过组合扩展功能:
java复制class ObservableList<E> implements List<E> {
private final List<E> delegate;
private final List<ListChangeListener<E>> listeners = new ArrayList<>();
public ObservableList(List<E> delegate) {
this.delegate = delegate;
}
public void addListener(ListChangeListener<E> listener) {
listeners.add(listener);
}
@Override
public void add(int index, E element) {
delegate.add(index, element);
notifyListeners();
}
// 实现其他方法并通知监听器...
}
常用的第三方集合库:
编写兼容代码的建议:
使用JUnit测试集合:
java复制@Test
void testListOperations() {
List<String> list = new ArrayList<>();
assertTrue(list.isEmpty());
list.add("test");
assertEquals(1, list.size());
assertEquals("test", list.get(0));
}
在IDE中查看集合内容:
使用JMH进行集合性能测试:
java复制@Benchmark
@BenchmarkMode(Mode.AverageTime)
public void testArrayListIteration(Blackhole bh) {
List<Integer> list = new ArrayList<>(DATA);
for (Integer i : list) {
bh.consume(i);
}
}
集合反序列化的安全问题:
处理敏感数据的建议:
线程安全集合的选择:
Collections.synchronizedXXX():粗粒度锁CopyOnWriteArrayList:读多写少场景ConcurrentHashMap:高并发场景首选使用Jackson进行集合与JSON转换:
java复制ObjectMapper mapper = new ObjectMapper();
// 集合转JSON
String json = mapper.writeValueAsString(list);
// JSON转集合
List<String> list = mapper.readValue(json,
new TypeReference<List<String>>() {});
使用JPA/Hibernate时的集合映射:
java复制@Entity
class User {
@Id Long id;
@ElementCollection
Set<String> phoneNumbers;
@OneToMany
List<Order> orders;
}
集合与Stream的深度集成:
java复制List<String> result = collection.stream()
.filter(item -> item.startsWith("A"))
.map(String::toUpperCase)
.sorted()
.collect(Collectors.toList());
常见错误选择:
常见性能误解:
常见API误用:
Project Valhalla带来的变化:
可能的增强方向:
并发控制的演进:
在日均PV过亿的电商系统中:
金融行业对集合的特殊要求:
游戏服务器中的集合优化:
审查时应检查:
重点关注:
提高可读性的建议:
利用IDE功能提高效率:
使用工具发现集合问题:
集合调试专用工具: