Java8中分裂器、收集器和流的理解

我在理解 Java8中的 Stream接口方面遇到了麻烦,特别是在与 SpliteratorCollector接口有关的地方。我的问题是,我根本不能理解 SpliteratorCollector接口,因此,Stream接口对我来说仍然有些模糊。

SpliteratorCollector到底是什么,我如何使用它们?如果我愿意编写我自己的 Spliterator或者 Collector(或者在这个过程中编写我自己的 Stream) ,我应该做什么和不应该做什么?

我阅读了一些散布在网络上的例子,但是由于这里的一切仍然是新的,并受到变化的影响,例子和教程仍然非常稀少。

73560 次浏览

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

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

Collector结合了一个 reduce函数的规范(map-reduce 著名)和一个初始值,以及一个结合两个结果的函数(从而使来自 Spliterated 的工作流的结果能够结合起来)

例如,最基本的 Collector 将初始值为0,将一个整数添加到一个现有结果上,并通过添加它们来“组合”两个结果。这样就得到了一个分裂的整数流。

参见:

几乎可以肯定,您永远不必以用户的身份处理 Spliterator; 只有在您自己编写 Collection类型和 还有打算优化它们的并行操作时,才有必要这样做。

值得一提的是,Spliterator是一种对集合元素进行操作的方法,这种方法可以很容易地分离出集合的一部分,例如,因为你正在进行并行化,希望一个线程在集合的一部分上工作,一个线程在另一部分上工作,等等。

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

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

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

  • 求和,例如 Collectors.reducing(0, (x, y) -> x + y)
  • 附加的 StringBuilder,例如 Collector.of(StringBuilder::new, StringBuilder::append, StringBuilder::append, StringBuilder::toString)

下面是使用预定义收集器执行常见的可变简化任务的示例:

 // 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));

接口 Spliterator-是 小溪的核心功能。

stream()parallelStream()默认方法在 Collection接口中显示。这些方法通过对 spliterator()的调用使用 Spliterator:

...


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


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


...

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

在其他方法中,有两种最重要的方法来理解分裂者: