java8流和多个
我很好奇,如何在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。
假设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); });
尝试使用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
使用stream的优点是可以选择使用parallelStream()
而不是stream()
。 在某些情况下,它可能比简单的循环更有效。
只是做一个总和,我会像Ł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()); });
现在你看到有两种实现: Accumulator和Atomic ,这两者之间的选择是另一个问题:
java 8:LongAdder和LongAccumulator是AtomicLong的首选吗?
我会这样做一个简单的黑客:
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中他们已经引入了有效的最终概念。 这意味着,您只分配了一次。