问题
我无法理解Java 8中的Stream
接口,特别是它与Spliterator
和2338448578接口有关。我的问题是我根本无法理解Spliterator
和666163460接口,因此Stream
接口对我来说仍然有点模糊。
究竟是什么aSpliterator
和aCollector
,我该如何使用它们?如果我愿意写自己的Spliterator
或Collector
(可能是我自己的Stream
),我应该怎么做而不是做什么?
我阅读了一些散布在网络上的例子,但由于这里的所有内容都是新的并且可能会有变化,因此示例和教程仍然非常稀少。
#1 热门回答(129 赞)
你几乎肯定永远不必与用户交易Spliterator
;它应该只是你自己写Collection
类型并且需要优化并行操作才能对它们进行优化。
对于它的价值,aSpliterator
是一种操作集合元素的方式,它可以很容易地分离出部分集合,例如因为你是并行化的,并且希望一个线程可以在集合的一个部分上工作,一个线程可以在另一个部分上工作,等等。
基本上你永远不应该将类型为Stream
的值保存到变量中.Stream
有点像anIterator
,因为它是一个一次性使用的对象,你几乎总是在一个流畅的链中使用,就像在Javadoc示例中一样:
int sum = widgets.stream()
.filter(w -> w.getColor() == RED)
.mapToInt(w -> w.getWeight())
.sum();
Collector
是la map / reduce中"reduce"操作的最通用,抽象可能的版本;特别是,它需要支持并行化和完成步骤。 Collector
的示例包括:
- 求和,例如Collectors.reducing(0,(x,y) - > x y)
- StringBuilder追加,例如Collector.of(StringBuilder :: new,StringBuilder :: append,StringBuilder :: append,StringBuilder :: toString)
#2 热门回答(82 赞)
Spliterator
基本上是指"可拆分的迭代器"。
单线程可以遍历/处理整个Spliterator本身,但是Spliterator还有一个方法trySplit()
,它将为其他人(通常是另一个线程)"拆分"一个部分进行处理 - 使当前的分裂器工作量减少。
Collector
将areduce
function(map-reduce fame)的规范与初始值相结合,并将两个结果组合起来的值(从而使得Spliterated工作流的结果能够合并。)
例如,最基本的收集器的初始值为0,在现有结果上添加一个整数,并通过添加它们来"组合"两个结果。从而总结了一个分裂的整数流。
看到:
- Spliterator.trySplit()
- 收集者<T,A,R>
#3 热门回答(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));