Lambda 聚合两个以上的属性Java 8

Lambda 聚合两个以上的属性Java 8,lambda,java-8,sum,field,aggregate,Lambda,Java 8,Sum,Field,Aggregate,很简单,我有 class Per{ int a; long b; double c; String d; } 假设我有3000个类型为Per的对象,并收集在列表pers 现在我想实现:- 如果对象为空或d为null或blank a之和 b之和 对c 老办法是 someOperation实现并不重要,因为它可能简单也可能复杂 如何通过Java8流和lambda表达式实现这一点 一个可能的答案是这样的 int totalA = 0; long totalB=0

很简单,我有

 class Per{
    int a;
    long b;
    double c;
    String d;
}
假设我有3000个类型为
Per
的对象,并收集在
列表pers

现在我想实现:-

  • 如果对象为空或
    d
    null
    blank
  • a之和
  • b之和
  • 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使用
供应商
重新使用过滤流,然后应用映射和聚合操作

2按收集过滤后的
,然后按


注意,我没有在这里进行任何类型的分组,也不能为每个
创建新的
,也不能更新提供的对象。编写自己的
累加器
类和自定义
收集器
,这是一项简单的任务

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, ...
}


编写您自己的
累加器
类和自定义的
收集器
,这是一项简单的任务

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, ...
}


无法为每个对象创建新对象的原因是什么?因为如果可以的话,
reduce
方法真的很有用。为什么不能为每个对象创建新对象?因为如果可以的话,
reduce
方法可能真的很有用有一种方法可以在过滤器中使用
谓词:
((谓词)Objects::nonNull)和(per->Objects.nonNull(per.d)和(p->p.d.trim().isEmpty())
@antobalaniuc你是对的,但是写
p!=null
比目标类型转换更简洁。有一种方法可以在过滤器中使用
谓词:
((谓词)对象::nonNull)和(per->Objects.nonNull(per.d.)和(p->p.d.trim().isEmpty())
@antobalaniuc你是对的,但写
p!=null
比目标类型转换更简洁。
Accumulator result = pers.stream()
    .filter(p -> p != null && p.d != null && !p.d.trim().isEmpty())
    .collect(Collector.of(Accumulator::new, Accumulator::accumulate, Accumulator::combine));