我很好奇,如何在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。
答案 0 :(得分:7)
假设slaContractList
是SlaContract
个对象的列表,并且它有构造函数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.reduce
和Stream.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中他们已经引入了有效的最终概念。这意味着,您只分配了一次。