我很难理解Java 8中的流
接口,特别是与spliterator
和collector
接口有关的部分。我的问题是,我根本无法理解spliterator
和collector
接口,因此,stream
接口对我来说仍然有些模糊。
什么是拆分器
和收集器
以及如何使用它们?如果我愿意编写自己的拆分器
或收集器
(在那个过程中可能还有自己的流
),我应该做什么,不应该做什么?
我读了一些散落在web上的例子,但由于这里的一切都是新的,并且可能会发生变化,所以例子和教程仍然非常稀少。
spliterator
的基本意思是“可拆分的迭代器”。
单个线程可以遍历/处理整个分裂器本身,但是分裂器也有一个trysplit()
方法,它将“分裂”出一个部分,供其他人(通常是另一个线程)处理--使当前分裂器的工作量更少。
collector
将reduce
函数的规范(map-reduce fame的)与初始值结合起来,并将一个函数结合两个结果(从而使分离的工作流的结果能够结合起来)
例如,最基本的收集器的初始vaue为0,在现有结果上添加一个整数,并通过添加两个结果来“组合”两个结果。从而对拆分的整数流求和。
参见:
spliterator.trysplit()
收集器
您几乎可以肯定地不必作为用户处理spliterator
;只有在您自己编写collection
类型并打算优化它们的并行化操作时,才有必要这样做。
就其价值而言,spliterator
是一种对集合元素进行操作的方式,可以很容易地将集合的一部分拆分出来,例如,因为您正在并行化,希望一个线程处理集合的一部分,一个线程处理另一部分,等等。
您基本上也不应该将stream
类型的值保存到变量中。stream
有点像迭代器
,因为它是一个一次性使用的对象,您几乎总是在fluent链中使用,如Javadoc示例中所示:
int sum = widgets.stream()
.filter(w -> w.getColor() == RED)
.mapToInt(w -> w.getWeight())
.sum();
collector
是map/reduce中“reduce”操作的最概括、最抽象的可能版本;特别是,它需要支持并行化和最终化步骤。收集器
的示例包括:
收集器。reducing(0,(x,y)->x+y)
Collector.of(StringBuilder::New,StringBuilder::Append,StringBuilder::Append,StringBuilder::ToString)
我试图了解是如何工作的,以及拆分器是如何设计的。我认识到可能是更重要的方法之一,但是当我看到一些第三方实现时,有时我看到他们的拆分器无条件地为返回null。 问题: 普通迭代器和无条件返回null的拆分器有何不同?这样的分裂者似乎违背了分裂的目的
与之间的差异: > 它们可能有不同的特点: 这里讨论的似乎是另一个毫无意义的流拆分器特性策略(并行计算似乎更好):深入理解Java8和Java9中的拆分器特性 在本例中,从禁用拆分功能的顺序流创建了一个拆分器(返回null)。当以后需要转换回一个流时,该流不会从并行处理中受益。一种耻辱。 最大的问题是:作为解决办法,在调用之前总是将流转换为并行流会有什么主要影响?
我有以下课程。 我希望能够按年龄分组,然后收集人名列表,而不是人名对象本身;所有这些都在一个漂亮的lamba表达式中。 为了简化所有这些,我链接了当前的解决方案,该解决方案存储按年龄分组的结果,然后迭代它以收集名称。 当前解决方案 不理想,为了学习,我想有一个更优雅、更高效的解决方案。
在java 8中,流API帮助我们以非常干净和更少的代码完成工作。我是这些流API的忠实粉丝。但是很少有操作能够帮助解决同一类型的问题,也不确定何时使用哪种操作,虽然在两者之间进行选择并不困难,但只想知道任何一种操作都有针对这些操作的特定用例。我所说的操作是:- 中间操作:-最小值和最大值 终端操作:
这可能是一个基本问题,但是有人能解释一下和之间的主要区别并给出一些例子吗?
所以我试图使用Java8流Collectors.toMap添加元素到新创建的Map。 要创建的映射可能包含其某些键的空值。这对于HashMap来说是完全可以接受的,当我使用stream forEach添加成员时,它会按预期工作: msgRouteProps是一个映射,其中键和值都是非空的。请注意,ReflectionUtil。getNamedMethod()调用可能会返回null,我希望将其放入结