非常简单,我有
class Per{
int a;
long b;
double c;
String d;
}
假设我有3000个Per
类型的对象,并收集在List<Per> pers
现在我想实现: -
d
为null
或blank
a
b
c
旧方式
int totalA = 0; long totalB = 0l; long totalC = 0l;
for (Per per : pers) {
if (per.d != null && !per.d.trim().equals("")) {
totalA += per.a;
totalB += per.b;
totalC += someOperation(per.c);
}
}
someOperation
实施并不重要,因为它可能很简单或复杂。
如何通过Java8流和lambda表达式实现这一目标?
可能的答案是这样的
int totalA = 0; long totalB=0l;
pers.stream().filter(p->{
if(p == null || p.d == null || p.d.trim().equals(""))
return false;
return true;
}).forEach(per->{
totalA += per.a;
totalB += per.b;
});
但是totalA和totalB必须是最终的或有效的最终
我心中的其他可能性是:
1使用Supplier
作为suggested重复使用过滤后的流,然后应用地图和汇总操作。
2收集已过滤的Per
,然后执行forEach
注意我未在此处进行任何类型的分组,无法创建新的Per
或更新提供的对象。
答案 0 :(得分:5)
编写自己的Accumulator
课程和自定义Collector
,然后这是一项简单的任务。
class Accumulator {
private int a = 0;
private long b = 0L;
private double c = 0d;
public void accumulate(Per p) {
a += p.a;
b += p.b;
c += someOperation(p.c);
}
public Accumulator combine(Accumulator acc) {
a += acc.a;
b += acc.b;
c += acc.c;
return this;
}
// getter, hashCode, ...
}
Accumulator result = pers.stream()
.filter(p -> p != null && p.d != null && !p.d.trim().isEmpty())
.collect(Collector.of(Accumulator::new, Accumulator::accumulate, Accumulator::combine));