Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/apache-spark/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Apache spark Java 8流#collect vs.Spark PairRDDFunctions#combineByKey_Apache Spark_Java 8 - Fatal编程技术网

Apache spark Java 8流#collect vs.Spark PairRDDFunctions#combineByKey

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();

我不熟悉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();
    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框架。它在以下四个步骤中工作:

  • 将问题分解为几个可以并行执行的部分

  • 对于每个部分,初始化一个可变容器以保存部分结果

  • 对于零件中的每个元素,将其合并到第2步中创建的容器中

  • 最后一步,合并来自所有部分的容器,合并的结果容器将是collect方法的结果


  • 不确定我是否理解正确。

    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可以跨进程并行(这是一个分布式计算框架)