collection接口

原文: https://docs.oracle.com/javase/tutorial/collections/interfaces/collection.html

Collection 表示一组称为其元素的对象。 Collection接口用于传递需要最大通用性的对象集合。例如,按照惯例,所有通用集合实现都有一个带有Collection参数的构造器。此构造器(称为转换构造器)初始化新集合以包含指定集合中的所有元素,无论给定集合的子接口或实现类型如何。换句话说,它允许你转换集合的类型。

例如,假设您有Collection<String> c,可能是ListSet或其他类型的Collection。这个习惯用法创建了一个新的ArrayListList接口的实现),最初包含c中的所有元素。

  1. List<String> list = new ArrayList<String>(c);

Or — if you are using JDK 7 or later — you can use the diamond operator:

  1. List<String> list = new ArrayList<>(c);

Collection接口包含执行基本操作的方法,例如int size()boolean isEmpty()boolean contains(Object element)boolean add(E element)boolean remove(Object element)Iterator&lt;E&gt; iterator()

它还包含对整个集合进行操作的方法,例如boolean containsAll(Collection&lt;?&gt; c)boolean addAll(Collection&lt;? extends E&gt; c)boolean removeAll(Collection&lt;?&gt; c)boolean retainAll(Collection&lt;?&gt; c)void clear()

还存在用于阵列操作的其他方法(例如Object[] toArray()<T&gt; T[] toArray(T[] a))。

在 JDK 8 及更高版本中,Collection接口还公开方法Stream&lt;E&gt; stream()Stream&lt;E&gt; parallelStream(),以从底层集合中获取顺序或并行流。 (有关使用流的更多信息,请参阅标题为聚合操作的课程。)

考虑到Collection代表一组对象,Collection接口可以实现您所期望的。它有方法告诉你集合中有多少元素(sizeisEmpty),检查给定对象是否在集合中的方法(contains),从集合中添加和删除元素的方法(addremove),以及在集合上提供迭代器的方法(iterator)。

add方法的定义通常足够,因此对于允许重复的集合以及不重复的集合是有意义的。它保证Collection在调用完成后将包含指定的元素,如果Collection因调用而改变,则返回true。类似地,remove方法被设计为从Collection中删除指定元素的单个实例,假设它包含要开始的元素,并且如果Collection被修改为结果则返回true

遍历集合

遍历集合的方法有三种:(1)使用for-each构造的聚合操作(2)和(3)使用Iterator

聚合操作

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

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

同样,您可以轻松地请求并行流,如果集合足够大并且您的计算机具有足够的核心,这可能是有意义的:

  1. myShapesCollection.parallelStream()
  2. .filter(e -> e.getColor() == Color.RED)
  3. .forEach(e -> System.out.println(e.getName()));

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

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

或者总结一下所有员工的工资:

  1. int total = employees.stream()
  2. .collect(Collectors.summingInt(Employee::getSalary)));

这些只是您可以对流和聚合操作执行的操作的几个示例。有关更多信息和示例,请参阅标题为聚合操作的课程。

Collections 框架一直提供许多所谓的“批量操作”作为其 API 的一部分。这些方法包括对整个集合进行操作的方法,例如containsAlladdAllremoveAll等。不要将这些方法与 JDK 8 中引入的聚合操作混淆。新聚合操作与新聚合操作之间的关键区别现有的批量操作(containsAlladdAll等)是旧版本都是变异,这意味着它们都修改了底层集合。相反,新的聚合操作不会修改底层集合。使用新的聚合操作和 lambda 表达式时,必须注意避免突变,以免将来引入问题,如果您的代码稍后从并行流运行。

for-each Construct

for-each构造允许您使用for循环简洁地遍历集合或数组 - 请参阅 for Statement 。以下代码使用for-each构造在单独的行上打印出集合的每个元素。

  1. for (Object o : collection)
  2. System.out.println(o);

如果需要, Iterator 是一个对象,它允许您遍历集合并有选择地从集合中删除元素。通过调用iterator方法获得集合的Iterator。以下是Iterator接口。

  1. public interface Iterator<E> {
  2. boolean hasNext();
  3. E next();
  4. void remove(); //optional
  5. }

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

请注意,Iterator.remove在迭代期间修改集合的安全方式;如果在迭代进行过程中以任何其他方式修改基础集合,则行为未指定。

需要时,请使用Iterator代替for-each构造:

  • 删除当前元素。 for-each构造隐藏了迭代器,因此您无法调用remove。因此,for-each构造不可用于过滤。
  • 并行迭代多个集合。

以下方法说明如何使用Iterator过滤任意Collection - 即遍历删除特定元素的集合。

  1. static void filter(Collection<?> c) {
  2. for (Iterator<?> it = c.iterator(); it.hasNext(); )
  3. if (!cond(it.next()))
  4. it.remove();
  5. }

这段简单的代码是多态的,这意味着无论实现如何,它都适用于*任何 _ Collection。此示例演示了使用 Java Collections Framework 编写多态算法是多么容易。

集合接口批量操作

批量操作对整个Collection执行操作。您可以使用基本操作实现这些速记操作,但在大多数情况下,此类实现效率较低。以下是批量操作:

  • containsAll - 如果目标Collection包含指定Collection中的所有元素,则返回true
  • addAll - 将指定Collection中的所有元素添加到目标Collection
  • removeAll - 从目标Collection中删除也包含在指定Collection中的所有元素。
  • retainAll - 从目标Collection中删除而非的所有元素也包含在指定的Collection中。也就是说,它仅保留目标Collection中也包含在指定Collection中的那些元素。
  • clear - 删除Collection中的所有元素。

如果在执行操作的过程中修改了目标Collection,则addAllremoveAllretainAll方法都返回true

作为批量操作功能的一个简单示例,请考虑以下习惯用法从Collectionc中删除指定元素e的所有实例。

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

更具体地说,假设您要从Collection中删除所有null元素。

  1. c.removeAll(Collections.singleton(null));

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

集合接口阵列操作

toArray方法作为集合和旧 API 之间的桥梁提供,这些 API 期望输入上的数组。数组操作允许将Collection的内容转换为数组。没有参数的简单形式创建了一个新的Object数组。更复杂的形式允许调用者提供数组或选择输出数组的运行时类型。

例如,假设cCollection。以下片段将c的内容转储到新分配的Object数组中,其长度与c中的元素数相同。

  1. Object[] a = c.toArray();

假设已知c仅包含字符串(可能因为c的类型为Collection&lt;String>)。以下片段将c的内容转储到新分配的String数组中,其长度与c中的元素数相同。

  1. String[] a = c.toArray(new String[0]);