1. Collection接口概述
在Java编程中,Collection接口是集合框架的根接口之一,它定义了所有集合类共有的基本操作方法。作为Java容器体系的核心,Collection接口位于java.util包中,为List、Set、Queue等子接口提供了统一的操作规范。
注意:Collection与Collections是两个完全不同的概念,前者是接口,后者是工具类,包含各种静态方法。
Collection接口的常用方法可以分为以下几类:
- 基础操作:添加、删除、判断包含等
- 批量操作:添加/删除一组元素
- 查询操作:获取集合大小、判空等
- 迭代操作:遍历集合元素
- 流式操作:Java 8新增的流处理
2. 核心方法详解
2.1 基础操作方法
add(E e):向集合中添加单个元素
java复制List<String> list = new ArrayList<>();
boolean isAdded = list.add("Java"); // 返回true表示添加成功
remove(Object o):移除指定元素
java复制Set<Integer> set = new HashSet<>();
set.add(1);
boolean isRemoved = set.remove(1); // 返回true表示元素存在并被移除
contains(Object o):判断集合是否包含指定元素
java复制Collection<String> coll = Arrays.asList("A", "B", "C");
boolean exists = coll.contains("B"); // 返回true
2.2 批量操作方法
addAll(Collection<? extends E> c):添加另一个集合的所有元素
java复制List<String> src = Arrays.asList("X", "Y");
List<String> dest = new ArrayList<>();
dest.addAll(src); // dest现在包含["X", "Y"]
removeAll(Collection<?> c):移除与指定集合共有的所有元素
java复制Set<Integer> set1 = new HashSet<>(Arrays.asList(1,2,3));
Set<Integer> set2 = new HashSet<>(Arrays.asList(2,3));
set1.removeAll(set2); // set1只剩[1]
retainAll(Collection<?> c):仅保留与指定集合共有的元素
java复制List<String> list1 = new ArrayList<>(Arrays.asList("A","B","C"));
List<String> list2 = Arrays.asList("B","C","D");
list1.retainAll(list2); // list1变为["B","C"]
2.3 查询与转换方法
size():返回集合中元素的数量
java复制Queue<Integer> queue = new LinkedList<>(Arrays.asList(1,2,3));
int count = queue.size(); // 返回3
isEmpty():判断集合是否为空
java复制Collection<Object> emptyColl = Collections.emptyList();
boolean isEmpty = emptyColl.isEmpty(); // 返回true
toArray():将集合转换为数组
java复制Set<String> set = new HashSet<>(Arrays.asList("A","B"));
Object[] array = set.toArray(); // 返回Object数组
String[] strArray = set.toArray(new String[0]); // 指定类型数组
3. 迭代与流式操作
3.1 迭代器使用
iterator():返回集合的迭代器
java复制List<String> languages = Arrays.asList("Java","Python","Go");
Iterator<String> it = languages.iterator();
while(it.hasNext()) {
System.out.println(it.next());
}
提示:在Java 5+中,推荐使用增强for循环简化迭代:
java复制for(String lang : languages) {
System.out.println(lang);
}
3.2 Java 8流式操作
stream():返回顺序流
java复制List<Integer> numbers = Arrays.asList(1,2,3,4,5);
long evenCount = numbers.stream()
.filter(n -> n%2 == 0)
.count(); // 返回2
parallelStream():返回并行流(适合大数据量处理)
java复制Set<String> words = new HashSet<>(Arrays.asList("a","bb","ccc"));
int totalLength = words.parallelStream()
.mapToInt(String::length)
.sum(); // 返回6
4. 实现类特性对比
不同Collection实现类的方法行为差异:
| 方法 | ArrayList | HashSet | LinkedList | TreeSet |
|---|---|---|---|---|
| add() | O(1) | O(1) | O(1) | O(log n) |
| remove() | O(n) | O(1) | O(1) | O(log n) |
| contains() | O(n) | O(1) | O(n) | O(log n) |
| get() | O(1) | 不支持 | O(n) | 不支持 |
5. 实战注意事项
- 并发修改异常:
java复制List<String> list = new ArrayList<>(Arrays.asList("A","B","C"));
// 错误示例 - 会抛出ConcurrentModificationException
for(String s : list) {
if(s.equals("B")) list.remove(s);
}
// 正确做法 - 使用迭代器的remove方法
Iterator<String> it = list.iterator();
while(it.hasNext()) {
if(it.next().equals("B")) it.remove();
}
- equals与hashCode影响:
java复制class Person {
String name;
// 必须正确重写equals和hashCode
@Override
public boolean equals(Object o) {...}
@Override
public int hashCode() {...}
}
Set<Person> set = new HashSet<>();
set.add(new Person("Alice"));
boolean exists = set.contains(new Person("Alice")); // 依赖正确的hashCode实现
- 性能优化技巧:
- 预分配ArrayList容量:
new ArrayList<>(1000) - 使用
containsAll()前先检查大小:if(coll1.size() >= coll2.size()) coll1.containsAll(coll2) - 批量操作优先:单次
addAll()比多次add()高效
6. 常见面试问题解析
- Collection与Collections的区别:
- Collection是接口,定义集合基本操作
- Collections是工具类,提供排序、同步等方法
- fail-fast机制:
java复制List<String> list = new ArrayList<>();
list.add("A");
Iterator<String> it = list.iterator();
list.add("B"); // 结构修改
it.next(); // 抛出ConcurrentModificationException
- 如何选择集合实现类:
- 需要快速随机访问:ArrayList
- 频繁插入删除:LinkedList
- 去重需求:HashSet
- 需要排序:TreeSet
- 线程安全:CopyOnWriteArrayList/ConcurrentHashMap
- Java 8新增方法:
java复制Collection<String> coll = new ArrayList<>();
coll.removeIf(s -> s.length() > 5); // 删除长度>5的元素
coll.forEach(System.out::println); // 方法引用遍历
7. 高级应用场景
- 集合视图模式:
java复制List<Integer> numbers = Arrays.asList(1,2,3);
// 不可修改视图
Collection<Integer> unmodifiable = Collections.unmodifiableCollection(numbers);
// 同步视图
Collection<Integer> syncColl = Collections.synchronizedCollection(numbers);
- 与数组互转的陷阱:
java复制List<String> list = new ArrayList<>();
list.add("Java");
// 返回的数组是副本
String[] array = list.toArray(new String[0]);
array[0] = "Modified";
System.out.println(list.get(0)); // 仍输出"Java"
- 自定义集合实现:
java复制class FixedSizeCollection<E> implements Collection<E> {
private final E[] elements;
private int size;
// 必须实现所有Collection方法
@Override
public int size() { return size; }
// ...其他方法实现
}
8. 性能调优实战
- 批量操作基准测试:
java复制List<Integer> list = new ArrayList<>();
// 方式1:单次添加
long start = System.nanoTime();
for(int i=0; i<100000; i++) list.add(i);
// 方式2:批量添加(快3-5倍)
list.addAll(IntStream.range(0, 100000).boxed().collect(Collectors.toList()));
- 初始化容量优化:
java复制// 不佳实践:默认容量10,多次扩容
Set<String> set1 = new HashSet<>();
// 最佳实践:预计算容量
Set<String> set2 = new HashSet<>(expectedSize * 4/3 + 1);
- 遍历方式性能比较:
- 传统for循环(ArrayList最快)
- 迭代器(通用性好)
- forEach(Java8+,代码简洁)
- 并行流(大数据量优势)
9. 常见问题排查
- ClassCastException:
java复制Collection raw = new ArrayList();
raw.add("String");
// 运行时异常
Set<Integer> set = new HashSet<>(raw);
- 内存泄漏:
java复制Collection<Object> cache = new HashSet<>();
Object value = new Object();
cache.add(value);
value = null; // 仍被cache引用,无法GC
- NPE防护:
java复制Collection<String> coll = getPossibleNullCollection();
// 安全写法
for(String s : coll != null ? coll : Collections.emptyList()) {
// 处理逻辑
}
10. 最佳实践总结
- 防御性编程:
java复制// 方法参数检查
public void process(Collection<?> input) {
if(input == null) {
return; // 或抛出IllegalArgumentException
}
// 处理逻辑
}
- 不可变集合:
java复制// Java 9+工厂方法
List<String> immutable = List.of("A", "B", "C");
// 传统方式
Set<Integer> unmodifiable = Collections.unmodifiableSet(new HashSet<>(...));
- 文档规范:
java复制/**
* 处理用户集合
* @param users 不能为null,元素不能为null
* @return 新集合,不会为null但可能为空
*/
public Collection<User> filterUsers(Collection<User> users) {
// 实现
}
- 现代Java特性:
java复制// 模式匹配(Java 16+)
if(collection instanceof List<?> list) {
// 直接使用list
}
// 记录类(Java 16+)
record Point(int x, int y) {}
Collection<Point> points = new ArrayList<>();
