场景:我有一个包含2个函数的对象 - >
<Integer> getA(); <Integer> getB();
我有一个对象列表,比如List<MyObject> myObject
。
目标迭代List并获取对象列表中A和B的总和。
我的解决方案
myObject.stream().map(a -> a.getA()).collect(Collectors.summingDouble());
myObject.stream().map(a -> a.getB()).collect(Collectors.summingDouble());
问题:如何同时执行这两项操作?这样我就不必在原始列表上迭代两次。
@Edit:我这样做是因为我使用的一些过滤器是O(n ^ 3)。两次这样做真的很糟糕。
基准:如果程序在i5上运行半小时,那么它是T还是2T真的很重要。这是在更少的数据上,如果我在群集上运行,我的数据也会更大。
如果你能在一行中做到这一点很重要!
答案 0 :(得分:3)
您需要编写另一个类来存储总值,如下所示:
public class Total {
private int totalA = 0;
private int totalB = 0;
public void addA(int a) {
totalA += a;
}
public void addB(int b) {
totalB += b;
}
public int getTotalA() {
return totalA;
}
public int getTotalB() {
return totalB;
}
}
然后使用
收集值Total total = objects.stream()
.map(o -> (A) o)
.collect(Total::new,
(t, a) -> {
t.addA(a.getA());
t.addB(a.getB());
},
(t1, t2) -> { });
//check total.getTotalA() and total.getTotalB()
您也可以使用AbstractMap.SimpleEntry<Integer, Integer>
替换Total
以避免编写新类,但它仍然有点奇怪,因为A / B不属于键值关系。
答案 1 :(得分:0)
最优化的可能仍然是for循环。虽然流选择具有并行性作为选项,但很可能很快变得有效。 将两个循环合二为一不一定更快。
一项改进是使用int
代替Integer
。
List<String> list = Arrays.asList("tom","terry","john","kevin","steve");
int n = list.stream().collect(Collectors.summingInt(String::length));
int h = list.stream().collect(Collectors.summingInt(String::hashCode));
我赞成这个解决方案。
如果有人做一个循环,有两种选择:
后者:
List<String> list = Arrays.asList("tom","terry","john","kevin","steve");
long nh = list.stream()
.collect(Collectors.summingLong((s) -> (s.hashCode() << 32) | s.length()));
int n = (int) nh;
int h = (int) (nh >> 32L);