一、简介

迭代元素是我们可以在集合上执行的最基本的操作之一。

在本教程中,我们将了解如何迭代 Set 的元素以及它与 List 或数组上的类似任务有何不同。

2. 访问集合中的元素

列表 和许多其他集合不同, 集合 不是连续的。它们的元素没有索引,并且根据实现的不同,它们可能无法维持顺序。

这意味着我们不能通过编号来询问集合中的特定元素。因此,我们不能使用典型的 for 循环或任何其他基于索引的方法。

2.1. 迭代器

迭代集合的最基本且最接近金属的方法是调用每个 Set 公开的 迭代器 方法:

Set<String> names = Sets.newHashSet("Tom", "Jane", "Karen");
Iterator<String> namesIterator = names.iterator();

然后我们可以使用获得的 迭代器 来一一获取该 Set 的元素 。最具标志性的方法是检查 迭代器while 循环中是否有下一个元素:

while(namesIterator.hasNext()) {
   System.out.println(namesIterator.next());
}

我们还可以使用Java 8中添加的 forEachRemaining 方法:

namesIterator.forEachRemaining(System.out::println);

我们还可以混合使用这些解决方案:

String firstName = namesIterator.next(); // save first name to variable
namesIterator.forEachRemaining(System.out::println); // print rest of the names

所有其他方法都将在幕后以某种方式使用 迭代器

3.

每个 Set 都公开 spliterator() 方法。因此, Set* 可以轻松转换为 *Stream

names.stream().forEach(System.out::println);

我们还可以利用丰富的 Streams API来创建更复杂的管道。例如,让我们映射、记录集合中的元素,然后将其缩减为单个字符串:

String namesJoined = names.stream()
    .map(String::toUpperCase)
    .peek(System.out::println)
    .collect(Collectors.joining());

4. 增强循环

虽然我们不能使用简单的索引 for 循环来迭代 Set ,但我们可以使用 Java 5 中引入的增强循环功能:

for (String name : names) {
    System.out.println(name);
}

5. 用索引迭代

5.1.转换为数组

Set 没有索引,但我们可以人为地添加索引。一种可能的解决方案是简单地 Set 转换为一些更易于访问的数据结构,例如数组

Object[] namesArray = names.toArray();
for (int i = 0; i < namesArray.length; i++) {
    System.out.println(i + ": " + namesArray[i]);
}

请注意,单独转换为数组将迭代 Set 一次。因此,就复杂性而言,我们将迭代 Set 两次。如果性能至关重要,这可能是一个问题。

5.2.带索引的压缩

另一种方法是创建一个索引并使用我们的 Set 对其进行压缩。虽然我们可以使用普通 Java 来完成此操作,但有一些库专门为此提供了工具。

例如,我们可以使用Vavr的流:

Stream.ofAll(names)
  .zipWithIndex()
  .forEach(t -> System.out.println(t._2() + ": " + t._1()));

六、总结

在本教程中,我们了解了迭代 Set 实例的元素的各种方法。我们探讨了迭代器、流和循环的用法以及它们之间的差异。

与往常一样,示例可以在 GitHub 上找到。