4.2 Collection接口

所有通用集合实现都有一个带有Collection参数的构造函数,此构造函数(称为转换构造函数)初始化新集合以包含指定集合中的所有元素。换句话说,它允许转换集合的类型。这使得Collection接口有着非常高的通用性。

例如,有一个Collection<String> c,它可以转化成List、Set或其他类型的Collection。以下是代码示例:

Collection接口包含执行基本操作的方法,例如int size()、boolean isEmpty()、boolean contains(Object element)、boolean add(E element)、boolean remove(Object element)和Iterator<E> iterator()。

Collection接口还包含对整个集合进行操作的方法,例如boolean containsAll(Collection<?> c)、boolean addAll(Collection<? extends E> c)、boolean removeAll(Collection<?> c)、boolean retainAll(Collection<?> c)和void clear()。

Collection接口还存在用于数组操作的附加方法,例如Object[] toArray()和<T> T[] toArray(T[] a)。

在JDK 8及更高版本中,Collection接口还公开方法Stream<E> stream()和Stream<E> parallelStream(),以从底层集合中获取顺序或并行流。有关流的更多信息可以参阅第13章。

4.2.1 遍历集合

Java提供了3种遍历集合的方法:使用聚合操作、使用for-each和使用迭代器。

1.使用聚合操作

在JDK 8及更高版本中,迭代集合的首选方法是获取流并对其执行聚合操作。聚合操作通常与Lambda表达式结合使用,以使用较少的代码使编程更具表现力。以下代码按顺序遍历一组形状并打印出红色对象:

   myShapesCollection.stream()
   .filter(e  - > e.getColor()== Color.RED)
   .forEach(e  - > System.out.println(e.getName()));

使用此API收集数据的方法有很多种。例如,可能希望将Collection的元素转换为String对象,然后将它们连接起来,用逗号分隔:

   String joined = elements.stream()
       .map(Object::toString)
       .collect(Collectors.joining(", "));

或者用于统计所有员工的工资:

   int total = employees.stream()
   .collect(Collectors.summingInt(Employee::getSalary)));
2.使用for-each

for-each允许使用for循环简明地遍历集合或数组。以下代码示例使用for-each在单独的行上打印出集合的每个元素:

3.使用迭代器

使用迭代器Iterator对象可以遍历集合并有选择地从集合中删除元素。通过调用集合的iterator方法来获得集合的Iterator。以下是Iterator接口:

如果迭代器具有更多元素,则hasNext方法返回true,并且下一个方法返回迭代中的下一个元素。remove方法从基础Collection中删除next返回的最后一个元素。每次调用next时,只调用remove方法一次,如果违反此规则就抛出异常。

比如在下面的例子中需要过滤特定的元素,则应选择使用Iterator而不是for-each:

4.2.2 集合接口批量操作

批量操作对整个集合执行操作。虽然可以使用基本操作来实现,但是在大多数情况下此类实现往往效率比较低。以下是批量操作:

· containsAll:如果目标Collection包含指定Collection中的所有元素,就返回true。

· addAll:将指定Collection中的所有元素添加到目标Collection。

· removeAll:从目标Collection中删除包含在指定Collection中的所有元素。

· retainAll:从目标Collection中删除所有未包含在指定Collection中的元素。也就是说,它仅保留目标Collection中也包含在指定Collection中的那些元素。

· clear:从集合中删除所有元素。

如果在执行操作的过程中修改了目标Collection,那么addAll、removeAll和retainAll方法会返回true。

下面是批量操作功能的一个简单示例,用于从Collection中删除指定元素的所有实例e:

   c.removeAll(Collections.singleton(e));

假设要从Collection中删除所有null元素,代码如下:

Collections.singleton是一个静态工厂方法,返回一个只包含指定元素的不可变Set。