Collection 接口(java.util.Collection)是 Java 集合 API 的核心根接口之一。虽然你无法直接实例化 Collection 接口本身,而需要实例化其具体子类型(如 ArrayList、HashSet 等),但这些子类型都遵循相同的方法签名规范,因此你通常可以将它们统一视为 Collection 类型来处理。这种设计体现了面向对象编程的多态特性,使得代码能够灵活地适配不同的集合实现,同时保持接口调用的一致性。
如上所述,你并不是直接创建一个 Collection 实例,而是创建一个 Collection 子类型的实例。下面是创建 List 的示例,List 是 Collection 的子类型:
// 创建了一个 ArrayList 对象 Collection collection = new ArrayList(); Collection collection = new HashSet();
注意,上述示例适用于 Collection 的每个子类型。
以下接口(集合类型)扩展了 Collection 接口:
List 有序集合,允许重复元素,可通过索引访问
Set 不允许重复元素的集合,通常无序
SortedSet 继承自 Set,元素按自然顺序或自定义比较器排序
NavigableSet 继承自 SortedSet,提供导航方法(如获取小于 / 大于特定值的元素)
Queue 按特定顺序(通常是 FIFO)处理元素的集合,用于实现队列
Deque 双端队列,允许在两端插入和移除元素,兼具队列和栈的特性
在 Java 中,没有提供可用的 Collection 接口实现(即没有具体类是直接实现 Collection 接口,而是实现了它的子接口),因此你必须使用列出的其中一个子类型。Collection 接口只是定义了一组方法(行为),这些 Collection 子类型共享这些方法(可以理解为 Collection 是对一堆接口的再次抽象,提取出这些接口的公共特性)。这样就可以忽略你使用的是哪种特定类型的 Collection,而只将其视为 Collection。
下面是一个对 Collection 进行操作的方法:
package com.hxstrive.java_collection; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; public class MyCollectionUtil { // 定义一个方法,接收 Collection 参数 // 通过迭代器迭代 Collection 参数中的内容 public static void doSomething(Collection collection) { Iterator iterator = collection.iterator(); while (iterator.hasNext()) { Object object = iterator.next(); System.out.println(object); } } public static void main(String[] args) { // 使用 ArrayList 具体类作为参数 Collection collection1 = new ArrayList(); collection1.add("one"); collection1.add("two"); collection1.add("three"); doSomething(collection1); // 使用 HashSet 具体类作为参数 Collection collection2 = new HashSet(); collection2.add("11"); collection2.add("22"); collection2.add("33"); doSomething(collection2); } }
运行结果:
one two three 11 22 33
无论你使用的是哪种 Collection 子类型,都有几种标准方法可以将元素添加到 Collection 中。通过 add() 方法可以向 Collection 中添加元素。例如:
package com.hxstrive.java_collection; import java.util.Collection; import java.util.HashSet; import java.util.ArrayList; public class CollectionAddExamples { public static void main(String[] args) { String anElement = "an element"; Collection<String> collection = new HashSet<>(); // 1. 添加单个元素 boolean didCollectionChange = collection.add(anElement); System.out.println("添加单个元素是否成功: " + didCollectionChange); // 2. 添加另一个集合中的所有元素 Collection<String> anotherCollection = new ArrayList<>(); anotherCollection.add("element 2"); anotherCollection.add("element 3"); boolean allAdded = collection.addAll(anotherCollection); System.out.println("添加集合中所有元素是否成功: " + allAdded); // 打印结果 System.out.println("集合中的所有元素:"); for (String element : collection) { System.out.println("- " + element); } } }
运行结果:
添加单个元素是否成功: true 添加集合中所有元素是否成功: true 集合中的所有元素: - element 3 - element 2 - an element
上述代码中,add() 方法用于将指定元素添加到集合中,其返回值为 boolean 类型:当集合因本次添加操作发生改变时,返回 true;若集合未发生变化,则返回 false。具体行为会因集合类型不同而有所差异:对于 Set 这类不允许重复元素的集合,若待添加元素已存在,add () 方法会放弃添加且返回 false,集合保持不变;而对于 List 这类允许重复元素的集合,即便元素已存在,add () 方法仍会执行添加操作,使该元素在集合中出现多次,此时返回 true。
而 addAll() 方法将作为参数传递的 Collection 中的所有元素添加到集合中,集合对象本身不会被添加,只添加其元素。如果以集合作为参数调用 add() 方法,那么添加的将是集合对象本身,而不是其元素。
remove() 方法从集合中移除给定的元素,如果被移除的元素在集合中存在并已被移除,则 remove() 方法返回 true。如果元素不存在,remove() 方法返回 false。例如:
package com.hxstrive.java_collection; import java.util.Collection; import java.util.HashSet; public class CollectionRemoveExample { public static void main(String[] args) { // 创建集合并添加元素 Collection<String> collection = new HashSet<>(); collection.add("apple"); collection.add("banana"); collection.add("cherry"); System.out.println("初始集合: " + collection); // 移除存在的元素 boolean wasRemoved1 = collection.remove("banana"); System.out.println("是否移除了 'banana': " + wasRemoved1); System.out.println("移除后集合: " + collection); // 移除不存在的元素 boolean wasRemoved2 = collection.remove("date"); System.out.println("是否移除了 'date': " + wasRemoved2); System.out.println("操作后集合: " + collection); // 对于List集合的移除示例(会移除第一个匹配的元素) Collection<String> list = new java.util.ArrayList<>(); list.add("apple"); list.add("apple"); // 添加重复元素 System.out.println("\nList初始集合: " + list); boolean wasListElementRemoved = list.remove("apple"); System.out.println("List中是否移除了 'apple': " + wasListElementRemoved); System.out.println("List移除后集合: " + list); // 仅移除第一个匹配元素 } }
运行结果:
初始集合: [banana, apple, cherry] 是否移除了 'banana': true 移除后集合: [apple, cherry] 是否移除了 'date': false 操作后集合: [apple, cherry] List初始集合: [apple, apple] List中是否移除了 'apple': true List移除后集合: [apple]
注意:remove(Object o) 方法会从集合中移除第一个与指定元素相等的对象。对于 Set 集合(如 HashSet),由于不允许重复元素,移除操作只会影响最多一个元素。对于 List 集合(如 ArrayList),会移除第一个匹配的元素,保留后续可能存在的相同元素。
除了 remove() 方法,还提供了批量删除方法 removeAll(),该方法会删除作为参数传递给该方法的集合中的所有元素。如果 Collection 参数包含任何未在目标集合中找到的元素,这些元素将被忽略。示例:
package com.hxstrive.java_collection; import java.util.Collection; import java.util.HashSet; import java.util.ArrayList; public class CollectionRemoveAllExample { public static void main(String[] args) { // 创建目标集合并添加元素 Collection<String> collection = new HashSet<>(); collection.add("a"); collection.add("b"); collection.add("c"); collection.add("d"); collection.add("e"); System.out.println("初始集合: " + collection); // 创建包含要删除元素的集合 Collection<String> objectsToRemove = new ArrayList<>(); objectsToRemove.add("b"); objectsToRemove.add("d"); objectsToRemove.add("f"); // 这个元素在目标集合中不存在 // 执行批量删除 boolean didChange = collection.removeAll(objectsToRemove); System.out.println("集合是否发生变化: " + didChange); System.out.println("删除后集合: " + collection); // 对List集合的批量删除示例 Collection<String> list = new ArrayList<>(); list.add("x"); list.add("y"); list.add("x"); list.add("z"); System.out.println("\nList初始集合: " + list); Collection<String> listToRemove = new ArrayList<>(); listToRemove.add("x"); boolean listChanged = list.removeAll(listToRemove); System.out.println("List是否发生变化: " + listChanged); System.out.println("List删除后集合: " + list); // 所有"x"都会被删除 } }
运行结果:
初始集合: [a, b, c, d, e] 集合是否发生变化: true 删除后集合: [a, c, e] List初始集合: [x, y, x, z] List是否发生变化: true List删除后集合: [y, z]
注意,removeAll() 方法会删除目标集合中所有存在于参数集合中的元素,方法返回值为 boolean,表示目标集合是否因该操作发生了变化(true-表示发生了变化,false-表示未发生变化)。对于参数集合中不存在于目标集合的元素,会被自动忽略。对于允许重复元素的集合(如 ArrayList),会删除所有匹配的元素,而不仅仅是删除第一个。
retainAll() 方法的作用与 removeAll() 相反。它不会删除参数集合中的所有元素,而是保留所有这些元素,并删除所有其他元素。请记住,只有当这些元素已经包含在目标集合中时,它们才会被保留。在参数 “Collection”中发现的任何新元素,如果不在目标集合中,都不会被自动添加,只会被忽略。如下图:
上图中,当调用目标集合的 retainAll() 方法,参数集合作为参数时,目标集合仅会保留 1、3、5、7、9 五个元素,参数集合中的 11、13 元素也将被删除,因为它们不在目标集合中。
例如:
package com.hxstrive.java_collection; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; public class CollectionRetainAllExample { public static void main(String[] args) { // 创建两个源集合 Collection<String> colA = new ArrayList<>(); Collection<String> colB = new ArrayList<>(); // 向内添加元素 colA.addAll(Arrays.asList("1", "2", "3", "4", "5", "6", "7", "8", "9")); colB.addAll(Arrays.asList("1", "3", "5", "7", "9", "11", "13")); // 保留与colB共有的元素 boolean didChange = colA.retainAll(colB); System.out.println("是否发生变更: " + didChange); // true System.out.println("保留与colB交集后: " + colA); // [1, 3, 5, 7, 9] // 演示对空集合的操作 Collection<String> emptyCol = new ArrayList<>(); colA.retainAll(emptyCol); System.out.println("与空集合取交集后: " + colA); // [] } }
运行结果:
是否发生变更: true 保留与colB交集后: [1, 3, 5, 7, 9] 与空集合取交集后: []
注意,retainAll() 方法用于保留目标集合中与参数集合共有的元素(取交集),删除其他所有元素。该方法返回值为 boolean,表示目标集合是否因该操作发生了变化。当参数集合为空时,目标集合会被清空(因为没有共同元素)。
Collection 接口提供了两个方法用于检查集合是否包含一个或多个特定元素。分别是 contains() 和 containsAll() 方法。例如:
package com.hxstrive.java_collection; import java.util.Collection; import java.util.HashSet; public class CollectionContainsExamples { public static void main(String[] args) { // 创建主集合并添加元素 Collection<String> collection = new HashSet<>(); collection.add("apple"); collection.add("banana"); collection.add("cherry"); collection.add("date"); System.out.println("主集合元素: " + collection); // 1. 使用contains()检查单个元素是否存在 String checkElement1 = "banana"; boolean containsElement1 = collection.contains(checkElement1); System.out.println("是否包含 '" + checkElement1 + "': " + containsElement1); // true String checkElement2 = "grape"; boolean containsElement2 = collection.contains(checkElement2); System.out.println("是否包含 '" + checkElement2 + "': " + containsElement2); // false // 2. 使用containsAll()检查多个元素是否都存在 Collection<String> elements1 = new HashSet<>(); elements1.add("apple"); elements1.add("cherry"); boolean containsAll1 = collection.containsAll(elements1); System.out.println("\n是否包含所有元素 " + elements1 + ": " + containsAll1); // true Collection<String> elements2 = new HashSet<>(); elements2.add("banana"); elements2.add("grape"); // 不存在的元素 boolean containsAll2 = collection.containsAll(elements2); System.out.println("是否包含所有元素 " + elements2 + ": " + containsAll2); // false // 3. 检查空集合 Collection<String> emptyCollection = new HashSet<>(); boolean containsEmpty = collection.containsAll(emptyCollection); System.out.println("是否包含空集合中的所有元素: " + containsEmpty); // true (特殊情况) } }
运行结果:
主集合元素: [banana, date, apple, cherry] 是否包含 'banana': true 是否包含 'grape': false 是否包含所有元素 [apple, cherry]: true 是否包含所有元素 [banana, grape]: false 是否包含空集合中的所有元素: true
注意:
contains(Object o):判断集合中是否包含指定元素,返回true表示存在,false表示不存在。
containsAll(Collection<?> c):判断集合中是否包含参数集合中的所有元素,只有当所有元素都存在时才返回true,否则返回 false。当参数集合为空时,containsAll() 始终返回true(因为空集合中没有元素需要检查)。
contains() 和 containsAll() 方法的判断都是基于元素的 equals() 方法,因此集合中元素的类应正确实现 equals() 方法。
使用 size() 方法可以检查集合的大小。所谓 “大小 ”是指集合中元素的数量。下面是一个示例:
package com.hxstrive.java_collection; import java.util.Collection; import java.util.ArrayList; import java.util.HashSet; public class CollectionSizeExample { public static void main(String[] args) { // 演示不同集合的size()方法 Collection<String> arrayList = new ArrayList<>(); Collection<Integer> hashSet = new HashSet<>(); // 向ArrayList添加元素 arrayList.add("Java"); arrayList.add("Python"); arrayList.add("Java"); // ArrayList允许重复元素 int arrayListSize = arrayList.size(); System.out.println("ArrayList中的元素数量: " + arrayListSize); // 输出 3 System.out.println("ArrayList内容: " + arrayList); // [Java, Python, Java] // 向HashSet添加元素 hashSet.add(10); hashSet.add(20); hashSet.add(10); // HashSet不允许重复元素,此元素不会被添加 int hashSetSize = hashSet.size(); System.out.println("\nHashSet中的元素数量: " + hashSetSize); // 输出 2 System.out.println("HashSet内容: " + hashSet); // [10, 20] // 演示空集合的size() Collection<Double> emptyCollection = new ArrayList<>(); System.out.println("\n空集合的元素数量: " + emptyCollection.size()); // 输出 0 // 演示集合操作对size的影响 arrayList.remove("Python"); System.out.println("\n移除元素后ArrayList的大小: " + arrayList.size()); // 输出 2 } }
运行结果:
ArrayList中的元素数量: 3 ArrayList内容: [Java, Python, Java] HashSet中的元素数量: 2 HashSet内容: [20, 10] 空集合的元素数量: 0 移除元素后ArrayList的大小: 2
你可以遍历集合中的所有元素。方法是从集合中获取一个 Iterator,然后遍历该 Iterator。如下所示
package com.hxstrive.java_collection; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; public class CollectionIteratorExample { public static void main(String[] args) { // 创建集合并添加元素 Collection<String> collection = new HashSet<>(); collection.add("Apple"); collection.add("Banana"); collection.add("Cherry"); collection.add("Date"); System.out.println("集合中的元素:"); // 获取迭代器并遍历集合 Iterator<String> iterator = collection.iterator(); while (iterator.hasNext()) { // 注意:这里使用了泛型指定元素类型,避免强制类型转换 String element = iterator.next(); System.out.println(element); // 演示迭代过程中删除元素(HashSet中"Banana"会被删除) if ("Banana".equals(element)) { iterator.remove(); System.out.println("已删除元素: " + element); } } // 遍历后查看集合内容 System.out.println("\n删除元素后的集合: " + collection); } }
运行结果:
集合中的元素: Apple Cherry Date Banana 已删除元素: Banana 删除元素后的集合: [Apple, Cherry, Date]
也可以使用 Java 的“for-each”循环来迭代一个 Java 集合:
package com.hxstrive.java_collection; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; public class CollectionForEachExample { public static void main(String[] args) { // 创建集合并添加元素 Collection<String> collection = new HashSet<>(); collection.add("A"); collection.add("B"); collection.add("C"); collection.add("D"); System.out.println("使用增强for循环遍历HashSet:"); // 增强for循环遍历(适用于所有实现了Iterable接口的集合) for (String element : collection) { // 使用泛型指定类型,避免强制转换 System.out.println(element); } // 对比ArrayList的遍历顺序(有序) Collection<String> arrayList = new ArrayList<>(); arrayList.add("A"); arrayList.add("B"); arrayList.add("C"); arrayList.add("D"); System.out.println("\n使用增强for循环遍历ArrayList:"); for (String element : arrayList) { System.out.println(element); } // 演示遍历中尝试修改集合的错误(会抛出ConcurrentModificationException) System.out.println("\n演示遍历中修改集合的错误:"); try { for (String element : collection) { if ("B".equals(element)) { collection.remove(element); // 错误的修改方式 } } } catch (java.util.ConcurrentModificationException e) { System.out.println("发生异常: " + e.getMessage()); System.out.println("提示: 增强for循环中不能直接修改集合结构"); } } }
运行结果:
使用增强for循环遍历HashSet: A B C D 使用增强for循环遍历ArrayList: A B C D 演示遍历中修改集合的错误: 发生异常: null 提示: 增强for循环中不能直接修改集合结构
注意,增强 for 循环(for-each 循环)是遍历集合的简化语法,适用于所有实现了 Iterable 接口的集合。相比迭代器,增强 for 循环代码更简洁,但不支持在遍历过程中修改集合结构(会抛出ConcurrentModificationException)。配合泛型使用(如 Collection<String>)可以在遍历中直接获取指定类型的元素,避免类型转换,非常方便。若需要在遍历中删除元素,应使用迭代器的 remove() 方法而非增强 for 循环。