Apache spark Java 8流#collect vs.Spark PairRDDFunctions#combineByKey
我不熟悉Java8和流API,我正在练习它 我使用下面的代码来计算集合的最大值,看起来我已经正确编码了Apache spark Java 8流#collect vs.Spark PairRDDFunctions#combineByKey,apache-spark,java-8,Apache Spark,Java 8,我不熟悉Java8和流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();
@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用于一个进程内的并行编程,可能底层支持框架是Java fork/join框架。它在以下四个步骤中工作:
不确定我是否理解正确。Java流可以并行处理-它们有
并行方法。然而,它仍然是一台机器处理
@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);
}
基本上你的理解是好的。创建组合器返回可变结果,合并值定义如何将流的部分结果/元素添加到可变结果,合并组合器将少数组合器的可变结果合并到一个结果中
有些名称不同,解释如下:
- Spark的创建合并器=Stream的供应商
- Spark的Merge Values=流的累加器-累加意味着以某种方式合并少数结果
- Spark的合并合并器=流的合并器-对于Spark合并器,它是MergeValues函数,但是合并合并器的含义与流的合并器相同
Spark中的组合器和流的容器是相同的可变结果容器
Spark的处理是在多台机器上并行完成的。在一台机器上,语义是相同的(或者看起来是相同的-实现细节可能不同),但是流不能在集群上处理。1作为旁注,您不需要像AtomicInteger
这样的线程安全容器来处理Stream.collect(…)
,顺便说一下,使用这三个函数,确保一次不会有多个线程访问容器。所以您也可以使用intmax=data.parallelStream().collect(()->newint[]{Integer.MIN_VALUE},(a,i)->{if(i>a[0])a[0]=i;},(a,b)->{if(a[0]谢谢@holger,正如您使用数组一样,我使用AtomicInteger作为容器,可以更改其中的值。是的,使用AtomicInteger
或数组在语义上是相同的。但是AtomicInteger
是线程安全的,这种安全性带来的开销在这里是不必要的。谢谢@holger,我同意AtomicInteger涉及CAS和volatile,可确保内存可视性感谢@t-gawęda的回答。是的,我知道Java-8 Streams API只能在一个进程内并行(fork/join框架也适用于一个进程),而Spark可以跨进程并行(这是一个分布式计算框架)