在Aggregating with Streams中,Brian Goetz比较使用Stream.collect()填充集合并使用Stream.forEach()执行相同操作,并使用以下两个片段:
Set<String> uniqueStrings = strings.stream()
.collect(HashSet::new,
HashSet::add,
HashSet::addAll);
和
Set<String> set = new HashSet<>();
strings.stream().forEach(s -> set.add(s));
然后他解释道:
关键 区别在于,对于forEach()版本,多个线程正在尝试访问单个结果 容器同时使用,而使用parallel collect(),每个线程都有自己的本地结果 容器,其结果随后合并。
据我所知,只有当流是并行的时,多个线程才会在forEach()情况下工作。但是,在给出的示例中,forEach()在顺序流上运行(不调用parallelStream())。
那么,forEach()是否始终并行工作,或者代码片段应该调用parallelStream()而不是stream()。 (或者我错过了什么?)
答案 0 :(得分:8)
不,如果流不是并行的,则forEach()不会并行化。我认为他为了讨论而简化了这个例子。
作为证据,此代码位于AbstractPipeline类的evaluate方法(从forEach调用)中
None
答案 1 :(得分:1)
整个报价如下:
正如减少可以安全地并行化,只要组合功能是关联的并且没有干扰副作用,
private static final Key secret = MacProvider.generateKey(SignatureAlgorithm.HS256); private static final byte[] secretBytes = secret.getEncoded(); public static final String base64SecretBytes = Base64.getEncoder().encodeToString(secretBytes);
的可变减少可以安全地并行化,如果它满足某些简单的一致性要求(在{{1}的规范中概述) })。
然后你引用了什么:
关键区别在于,对于
Stream.collect()
版本,多个线程同时尝试访问单个结果容器,而使用并行collect()
,每个线程都有自己的本地结果容器,结果之后合并。
由于第一句话清楚地提到了并行化,我的理解是在 parallel 流的上下文中都提到了forEach()
和collect()
。