我是Java 8和Stream API的新手,我正在练习它。
我使用以下代码计算集合的最大值,看起来我已正确编码。
@Test
public void testStreamCollect() {
List<Integer> data = Arrays.asList(1, 22, 2, 3, 4, 5, 6, 31, 8, 10, 17, 52, 2, 3, 48, 11);
Stream<Integer> stream = data.parallelStream();
Supplier<AtomicInteger> createCombiner = () -> {
AtomicInteger initial = new AtomicInteger();
initial.set(Integer.MIN_VALUE);
return initial;
};
BiConsumer<AtomicInteger, Integer> mergeValue = (accum, ii) -> {
if (ii > accum.get()) {
accum.set(ii);
}
};
BiConsumer<AtomicInteger, AtomicInteger> mergeCombiner = (a, b) -> {
if (a.get() < b.get()) {
a.set(b.get());
}
};
AtomicInteger max = stream.collect(createCombiner, mergeValue, mergeCombiner);
System.out.println(max);
}
我要问的是:Stream#collect方法有三个参数,我将它们命名为createCombiner, mergeValue and mergeCombiner,
我之所以这样命名是因为我认为Stream#collect与Spark PairRDDFunctions#combineByKey
方法非常相似,它还具有`createCombiner,mergeValue,mergeCombiners函数作为参数,它是完整的签名
def combineByKeyWithClassTag[C](
createCombiner: V => C,
mergeValue: (C, V) => C,
mergeCombiners: (C, C) => C,
partitioner: Partitioner,
mapSideCombine: Boolean = true,
serializer: Serializer = null)(implicit ct: ClassTag[C]): RDD[(K, C)]
如果它们在功能上相同/相似,我会得出结论,Stream#collect用于一个进程内的并行编程,也许底层支持框架是Java fork / join框架。它的工作原理如下:< / p>
将问题分成几个可以并行执行的部分
对于每个部分,初始化一个可变容器以保存部分结果。
对于零件中的每个元素,将其合并到第二步中创建的容器中。
最后一步,合并所有部分的容器,合并后的结果容器将是collect方法的结果
不确定我是否理解正确。
答案 0 :(得分:2)
Java Streams可以并行处理 - 它们具有parallel
方法。但是,它仍然是单机处理。
基本上你的理解是可以的。 Create Combiner返回可变结果,Merge Values定义了如何将流的部分结果/元素添加到可变结果中,Merge Combiners合并了几个组合器&#39;可变结果成为一个结果。
有些名称不同,这里有解释:
Spark中的Combiner与Stream的容器
是相同的可变结果容器Spark的处理是在多台机器上并行完成的。在一台机器上,语义是相同的(或看起来相同 - 实现细节可能不同),但Streams无法在cluster.1上进行处理。