Java 聚合函数&;行为-并行流
下面是一个使用 聚合函数(Java 聚合函数&;行为-并行流,java,java-8,functional-programming,java-stream,Java,Java 8,Functional Programming,Java Stream,下面是一个使用 聚合函数(过滤器/映射/排序) & 行为(this::大写) & 终端操作(forEach) 对于给定的流(stream.of(…)) 为了避免在并行流中产生竞争条件,我了解到,我们需要额外的努力来明确地使行为在没有副作用(无状态)的情况下工作,如下所示 String capitalize(String s) { if (s.length() == 0) return s; return s.substring(0, 1)
过滤器
/映射
/排序
)
&
行为(this::大写
)
&
终端操作(forEach
)
对于给定的流(stream.of(…)
)
为了避免在并行流中产生竞争条件,我了解到,我们需要额外的努力来明确地使行为在没有副作用(无状态)的情况下工作,如下所示
String capitalize(String s) {
if (s.length() == 0)
return s;
return s.substring(0, 1)
.toUpperCase()
+ s.substring(1)
.toLowerCase();
聚合函数只对从流生成的每个元素应用行为
作为从流生成的元素(一次一个),没有非瞬态存储
没有任何额外的努力,聚合函数总是纯函数,没有任何副作用吗?这不会在并行流中产生竞争条件流API的一个关键点是,只要您的行为参数满足标准,所有操作都支持正确的并行处理。或者,如前所述: 相似 具有显式for循环的处理元素本质上是串行的。流通过将计算重新构造为聚合操作的管道,而不是每个元素上的命令操作,从而促进并行执行。所有流操作都可以串行或并行执行 除了被明确标识为不确定的操作,例如
findAny()
,流是顺序执行还是并行执行都不应改变计算结果
大多数流操作接受描述用户指定行为的参数,这些参数通常是lambda表达式。为了保持正确的行为,这些行为参数必须是无干扰的,并且在大多数情况下必须是无状态的。此类参数始终是函数接口(如Function)的实例,通常是lambda表达式或方法引用
注意,术语聚合操作更一般,适用于整个流操作,包括中间操作和终端操作。关于
map
和filter
的内容也适用于reduce
;还原函数应该是无副作用和无状态的。请注意,虽然collect
包含可变状态,但它是本地的,并且仍然满足非干扰标准。如果无状态,您仍然可以从外部查看collect
操作
您必须查看特定终端操作的文档,以了解并行执行可能会如何影响结果,如前面提到的findFirst
和findAny
之间的差异。在您的情况下,这是有问题的,因为它可能会同时无序地调用使用者,因此无法保证元素是按照前面的排序的
步骤所施加的顺序打印的。您应该在此处使用forEachOrdered
顺便说一句,您可以将方法static
大写,以强调它不依赖于此
实例的状态。或者将其简化为lambda表达式,
s->s.isEmpty()?s:s.substring(0,1).toUpperCase()+s.substring(1).toLowerCase()
流API的一个关键点是,只要行为参数满足标准,所有操作都支持正确的并行处理。或者,如前所述:
相似
具有显式for循环的处理元素本质上是串行的。流通过将计算重新构造为聚合操作的管道,而不是每个元素上的命令操作,从而促进并行执行。所有流操作都可以串行或并行执行
除了被明确标识为不确定的操作,例如findAny()
,流是顺序执行还是并行执行都不应改变计算结果
大多数流操作接受描述用户指定行为的参数,这些参数通常是lambda表达式。为了保持正确的行为,这些行为参数必须是无干扰的,并且在大多数情况下必须是无状态的。此类参数始终是函数接口(如Function)的实例,通常是lambda表达式或方法引用
注意,术语聚合操作更一般,适用于整个流操作,包括中间操作和终端操作。关于map
和filter
的内容也适用于reduce
;还原函数应该是无副作用和无状态的。请注意,虽然collect
包含可变状态,但它是本地的,并且仍然满足非干扰标准。如果无状态,您仍然可以从外部查看collect
操作
您必须查看特定终端操作的文档,以了解并行执行可能会如何影响结果,如前面提到的findFirst
和findAny
之间的差异。在您的情况下,这是有问题的,因为它可能会同时无序地调用使用者,因此无法保证元素是按照前面的排序的
步骤所施加的顺序打印的。您应该在此处使用forEachOrdered
顺便说一句,您可以将方法static
大写,以强调它不依赖于此
实例的状态。或者将其简化为lambda表达式,
s->s.isEmpty()?s:s.substring(0,1).toUpperCase()+s.substring(1).toLowerCase()
您可以编写过滤器/map/sorted
也可以作为有状态的,但在函数方面不鼓励这样做,也不太好programming@Saravana当数据是从一个流(一次一个)输入的,而不是您的本地缓冲区(列表/任何…)时,为什么
String capitalize(String s) {
if (s.length() == 0)
return s;
return s.substring(0, 1)
.toUpperCase()
+ s.substring(1)
.toLowerCase();