148

I am having trouble understanding the Stream interface in Java 8, especially where it has to do with the Spliterator and Collector interfaces. My problem is that I simply can't understand Spliterator and the Collector interfaces yet, and as a result, the Stream interface is still somewhat obscure to me.

What exactly is a Spliterator and a Collector, and how can I use them? If I am willing to write my own Spliterator or Collector (and probably my own Stream in that process), what should I do and not do?

I read some examples scattered around the web, but since everything here is still new and subject to changes, examples and tutorials are still very sparse.

4

4 回答 4

148

您几乎可以肯定永远不必Spliterator作为用户处理;仅当您Collection自己编写类型并且打算优化它们的并行操作时,才需要这样做。

对于它的价值,aSpliterator是一种对集合元素进行操作的方式,这种方式很容易拆分集合的一部分,例如,因为您正在并行化并希望一个线程处理集合的一部分,一个线程在另一部分工作,等等。

您本质上也不应该将类型值保存Stream到变量中。 Stream有点像Iterator,因为它是一次性使用的对象,您几乎总是会在流畅的链中使用它,如 Javadoc 示例中所示:

int sum = widgets.stream()
                  .filter(w -> w.getColor() == RED)
                  .mapToInt(w -> w.getWeight())
                  .sum();

Collector是“reduce”操作(la map/reduce)的最通用、最抽象的可能版本;特别是,它需要支持并行化和最终化步骤。s 的示例Collector包括:

  • 求和,例如Collectors.reducing(0, (x, y) -> x + y)
  • StringBuilder 附加,例如Collector.of(StringBuilder::new, StringBuilder::append, StringBuilder::append, StringBuilder::toString)
于 2013-10-07T22:26:39.340 回答
91

Spliterator基本上意味着“可拆分的迭代器”。

单线程可以遍历/处理整个 Spliterator 本身,但 Spliterator 也有一个方法trySplit()可以“拆分”一个部分供其他人(通常是另一个线程)处理 - 使当前的 spliterator 工作更少。

Collectorreduce(map-reduce 成名的)函数的规范与初始值和用于组合两个结果的函数相结合(从而使来自分离的工作流的结果能够被组合。)

例如,最基本的 Collector 的初始值为 0,将一个整数添加到现有结果中,并通过添加两个结果来“组合”两个结果。从而对拆分的整数流求和。

看:

于 2013-10-07T22:25:43.053 回答
5

接口Spliterator- 是Streams的核心特性。

和默认方法显示在界面中stream()。这些方法通过调用使用 Spliterator :parallelStream()Collectionspliterator()

...

default Stream<E> stream() {
    return StreamSupport.stream(spliterator(), false);
}

default Stream<E> parallelStream() {
    return StreamSupport.stream(spliterator(), true);
}

...

Spliterator 是一个内部迭代器,它将流分成更小的部分。这些较小的零件可以并行处理。

在其他方法中,理解 Spliterator 有两种最重要的方法:

于 2018-07-31T09:02:01.517 回答
5

以下是使用预定义收集器执行常见可变归约任务的示例:

 // Accumulate names into a List
 List<String> list = people.stream().map(Person::getName).collect(Collectors.toList());

 // Accumulate names into a TreeSet
 Set<String> set = people.stream().map(Person::getName).collect(Collectors.toCollection(TreeSet::new));

 // Convert elements to strings and concatenate them, separated by commas
 String joined = things.stream()
                       .map(Object::toString)
                       .collect(Collectors.joining(", "));

 // Compute sum of salaries of employee
 int total = employees.stream()
                      .collect(Collectors.summingInt(Employee::getSalary)));

 // Group employees by department
 Map<Department, List<Employee>> byDept
     = employees.stream()
                .collect(Collectors.groupingBy(Employee::getDepartment));

 // Compute sum of salaries by department
 Map<Department, Integer> totalByDept
     = employees.stream()
                .collect(Collectors.groupingBy(Employee::getDepartment,
                                               Collectors.summingInt(Employee::getSalary)));

 // Partition students into passing and failing
 Map<Boolean, List<Student>> passingFailing =
     students.stream()
             .collect(Collectors.partitioningBy(s -> s.getGrade() >= PASS_THRESHOLD));
于 2017-05-24T04:01:04.767 回答