java - 聚合函数和行为 - 并行流

标签 java java-8 functional-programming java-stream

下面是一个使用的示例,

聚合函数(过滤器/映射/排序),

&

行为(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.

请注意,术语聚合操作更为通用,适用于整个流操作,包括中间操作和终端操作。关于mapfilter的内容也适用于reduce;归约函数应该是无副作用且无状态的。请注意,虽然 collect 包含可变状态,但它是本地的,并且仍然满足无干扰标准。从外部,您仍然可以查看 collect 操作 is-if stateless。

您必须查看特定终端操作的文档,以了解并行执行可能如何影响结果,例如前面提到的 findFirstfindAny 之间的区别。在你的情况下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/

相关文章:

java - LocalDate:缺少方法 isEqualOrBefore 和 isEqualOrAfter

java - 在 Java 1.8.0_152 中使用 Math.round(double d) 时转换为 int

f# - F# "remove a lot of subtle bug"如何来自 OCaml "+"?

haskell - 除了安全之外,强打字还有其他好处吗?

java - 当网络不稳定时Android将文件从客户端发送到服务器的最佳方法

c# - 使用什么库进行 XML SOAP 调度

java - LongAdder 是 ID 生成器的错误选择吗?

具有折叠操作的 Scala 选项

java - 在您的 Android 应用程序上进行身份验证

java - PgBouncer 与 WildFly/Application Server 连接池的优势?