了解Java 8中的Spliterator,Collector和Stream


143

我在理解StreamJava 8中的接口时遇到了麻烦,尤其是与Spliteratorand Collector接口有关的接口。我的问题是我根本无法理解SpliteratorCollector接口的是,作为一个结果,Stream接口仍然有些模糊了我。

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

我阅读了一些分散在网络上的示例,但是由于此处的所有内容仍然是新内容并且随时可能更改,因此示例和教程仍然非常稀疏。

Answers:


142

几乎可以肯定,您永远不必以Spliterator用户身份进行处理。如果你在写它时,才需要Collection类型的自己,打算并行优化他们的操作。

就其价值而言,a Spliterator是一种操作集合中元素的方式,可以很容易地拆分出集合的一部分,例如,因为您要并行化并希望一个线程在集合的一部分上工作,一个线程在另一部分上工作,等等。

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

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

Collector是map / reduce的“ reduce”操作的最通用,抽象的版本;特别是,它需要支持并行化和完成步骤。的示例Collector包括:

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

31
Spliterator(S)还提供了一种流的可迭代不是一个Collection
波西米亚

2
我的意思是“从某种意义上说,在地图/缩小中意味着一种减少操作”
Louis Wasserman,2015年

1
Collectors.of已删除的Beta版的旧方法还是我缺少某些东西?为了完整起见,(x,y) -> x+y可以写成Integer::sum
让·弗朗索瓦·Savard

3
嗯,不,对不起,它是Collector.of,而不是Collectors.of。
Louis Wasserman

2
如果您要解释每个收集器的功能,那么收集器的示例将更有用。
MiguelMunoz

90

Spliterator 基本上是指“可拆分迭代器”。

单线程可以遍历/处理整个Splitter本身,但是Spliterator也有一种方法trySplit()可以“分割”一部分以供其他人(通常是另一个线程)进行处理-从而使当前的Splitizer的工作量减少。

Collector将一个reduce函数的规格说明(具有map-reduce的名声)与一个初始值结合在一起,并将一个函数结合起来以结合两个结果(从而可以合并来自分割工作流的结果)。

例如,最基本的收集器的初始值将为0,在现有结果上添加一个整数,并通过将它们相加来“合并”两个结果。因此,求和一个分离的整数流。

看到:


结合两个结果的值?
Jason Law

@JasonLaw-澄清了!谢谢你的建议。
托马斯W

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

2
这无法回答操作者的问题,此外,您的帖子也没有任何解释或说明。
2017年

4

接口Spliterator-是Streams的核心功能。

stream()parallelStream()默认的方法都在展示Collection界面。这些方法通过以下方式使用Spliterator spliterator()

...

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

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

...

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

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


“如果操作成功执行。。”您可能应该改写此字词。tryAdvance javadoc更清晰:´如果剩余元素存在,则对其执行给定的操作,返回true;否则,返回true。否则返回false。´
Piro说,请恢复Monica
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.