聚合两个以上的属性 Java 8
Aggregating more than two properties Java 8
为了简单起见,我有
class Per{
int a;
long b;
double c;
String d;
}
假设我有 3000 个 Per
类型的对象并收集在 List<Per> pers
中
现在我要实现:-
- 如果对象为空或
d
为 null
或 blank
则跳过
a
之和
b
之和
- 在
c
上执行的操作的聚合值
Old way is
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
实施并不重要,因为它可能简单也可能复杂。
How can I achieve this via Java8 streams and lambda expression?
一个可能的答案是这样的
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
或更新提供的对象。
写你自己的Accumulator
class和一个自定义的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));
为了简单起见,我有
class Per{
int a;
long b;
double c;
String d;
}
假设我有 3000 个 Per
类型的对象并收集在 List<Per> pers
现在我要实现:-
- 如果对象为空或
d
为null
或blank
则跳过
a
之和
b
之和
- 在
c
上执行的操作的聚合值
Old way is
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
实施并不重要,因为它可能简单也可能复杂。
How can I achieve this via Java8 streams and lambda expression?
一个可能的答案是这样的
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
或更新提供的对象。
写你自己的Accumulator
class和一个自定义的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));