java8流和多个

时间:2016-11-12 21:39:21

标签: java collections java-8 sum java-stream

我很好奇,如何在java8流中总结多个变量。

Integer wCPU = 0;
Double wnetwork = 0.0;
Double wMem = 0.0;

this.slaContractList.forEach(sla -> {
    wCPU += sla.getNumberOfCPUs();
    wnetwork += sla.getNetworkBandwith();
    wMem += sla.getMemory();
});

但是,这不能编译,因为lambda表达式中的变量应该是final。

4 个答案:

答案 0 :(得分:7)

假设slaContractListSlaContract个对象的列表,并且它有构造函数SlaContract(numberOfCPUs, networkBandwith, memory),您可以:

SlaContract sumContract = slaContractList.stream()
    .reduce(new SlaContract(0, 0.0, 0.0), (sla1, sla2) -> {
         return new SlaContract(sla1.getNumberOfCPUs() + sla2.getNumberOfCPUs(), sla1.getworkBandwith() + sla2.getworkBandwith(), sla1.getMemory() + sla2.getMemory());
    });

Double wnetwork = sumContract.getworkBandwith();
Double wMem = sumContract.getMemory();
Integer wCPU = sumContract.getNumberOfCPUs();

相同的解决方案,但对于简单的类:

Point sumPoint = pointsList.stream()
    .reduce(new Point(0, 0), (p1, p2) -> {
         return new Point(p1.x + p2.x, p1.y + p2.y);
    });

答案 1 :(得分:6)

尝试使用Stream.reduceStream.sum

Double wnetwork = slaContractList.stream()
            .mapToDouble(sla -> sla.getNetworkBandwith())
            .sum();

Double wMem = slaContractList.stream()
            .mapToDouble(sla -> sla.getMemory())
            .sum();

Integer wCPU = slaContractList.stream()
            .mapToInt(sla -> sla.getNumberOfCPUs())
            .sum();

请参阅https://docs.oracle.com/javase/tutorial/collections/streams/reduction.html

使用流的优势是使用parallelStream()而非stream()的选项。在某些情况下,它可能比简单循环更有效。

答案 2 :(得分:3)

只是做一个总和,我会像Łukasz答案那样使用流的求和运算,但是,对于解决“最终问题”的更通用的解决方案,你可以使用java.util.concurrent.atomic的类。它的目的是在流中使用并且是线程安全的,因此可以在并行流中使用。

AtomicInteger wCPU = new AtomicInteger();
DoubleAccumulator wnetwork = new DoubleAccumulator(Double::sum,0.d);
DoubleAccumulator wMem = new DoubleAccumulator(Double::sum,0.d);

this.slaContractList.forEach(sla -> {
    wCPU.addAndGet(sla.getNumberOfCPUs());
    wnetwork.accumulate(sla.getNetworkBandwith());
    wMem.accumulate(sla.getMemory());
});

现在您看到有两种实现方式:累加器和Atomic ,这两种方法之间的选择是另一个问题:

java 8 : Are LongAdder and LongAccumulator preferred to AtomicLong?

答案 3 :(得分:2)

我会这样做一个简单的黑客:

    Integer[] wCPU = new Integer[1];
    Double[] wnetwork = new Double[1];
    Double[] wMem = new Double[1];

    this.slaContractList.forEach(sla -> {
        wCPU[0] += sla.getNumberOfCPUs();
        wnetwork[0] += sla.getNetworkBandwith();
        wMem[0] += sla.getMemory();
    });

两者都可以选择final关键字,因为在Java 8中他们已经引入了有效的最终概念。这意味着,您只分配了一次。