下面是一个使用的示例,
聚合函数(过滤器
/映射
/排序
),
&
行为(this::capitalize
),
&
终端操作(forEach
),
使用给定的流(Stream.of(...)
),
Stream
.of("horatio", "laertes", "Hamlet", ...)
.filter(s -> toLowerCase (s.charAt(0)) == 'h') # aggregate_function(behavior)
.map(this::capitalize)
.sorted()
.forEach(System.out::println);
<小时/>
为了不在并行流中引发竞争条件,我了解到,我们需要付出额外的努力来显式地使行为在没有副作用(无状态)的情况下工作,如下所示,
String capitalize(String s) {
if (s.length() == 0)
return s;
return s.substring(0, 1)
.toUpperCase()
+ s.substring(1)
.toLowerCase();
aggregate_function 只是将行为应用于从流生成的每个元素。
<小时/>作为从流中生成的元素(一次一个),没有非 transient 存储,
在没有任何额外努力的情况下,聚合函数是否总是纯函数,没有任何副作用?不会在并行流中引发竞争条件
最佳答案
Stream API 的一个关键点是,只要您的行为参数符合标准,所有操作都支持正确的并行处理。或者,如the specification状态:
Parallelism
Processing elements with an explicit for-loop is inherently serial. Streams facilitate parallel execution by reframing the computation as a pipeline of aggregate operations, rather than as imperative operations on each individual element. All streams operations can execute either in serial or in parallel.
…
Except for operations identified as explicitly nondeterministic, such as
findAny()
, whether a stream executes sequentially or in parallel should not change the result of the computation.Most stream operations accept parameters that describe user-specified behavior, which are often lambda expressions. To preserve correct behavior, these behavioral parameters must be non-interfering, and in most cases must be stateless. Such parameters are always instances of a functional interface such as Function, and are often lambda expressions or method references.
请注意,术语聚合操作更为通用,适用于整个流操作,包括中间操作和终端操作。关于map
和filter
的内容也适用于reduce
;归约函数应该是无副作用且无状态的。请注意,虽然 collect
包含可变状态,但它是本地的,并且仍然满足无干扰标准。从外部,您仍然可以查看 collect
操作 is-if stateless。
您必须查看特定终端操作的文档,以了解并行执行可能如何影响结果,例如前面提到的 findFirst
和 findAny
之间的区别。在你的情况下forEach
是有问题的,因为它可能会无序地同时调用消费者,因此不能保证元素按照前面的 sorted
步骤所施加的顺序打印。您应该在此处使用 forEachOrdered
。
顺便说一句,您可以将您的 capitalize
方法设置为 static
以强调它不依赖于 this
实例的状态。或者将其简化为 lambda 表达式,
s -> s.isEmpty()? s: s.substring(0, 1).toUpperCase() + s.substring(1).toLowerCase()
关于java - 聚合函数和行为 - 并行流,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47546109/