【发布时间】:2017-12-05 03:02:38
【问题描述】:
我是使用 Java 8 Stream API 的新手,但我希望用它来解决以下问题。假设我有一个名为 InputRecord 的 POJO,其中包含 name、fieldA 和 fieldB 属性,它们可以表示以下每行记录:
name | fieldA | fieldB
----------------------
A | 100 | 1.1
A | 150 | 2.0
B | 200 | 1.5
A | 120 | 1.3
InputRecord 看起来像:
public class InputRecord {
private String name;
private Integer fieldA;
private BigDecimal fieldB;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getFieldA() {
return fieldA;
}
public void setFieldA(Integer fieldA) {
this.fieldA = fieldA;
}
public BigDecimal getFieldB() {
return fieldB;
}
public void setFieldB(BigDecimal fieldB) {
this.fieldB = fieldB;
}
}
以上这四条记录需要合并成两条按名称分组的记录,其中:
- 属性
fieldA被求和 - 属性
fieldB被求和 - 合并的记录包括一个
fieldC属性,它是fieldA和fieldB的累加和相乘的结果。
因此上面的结果是:
name | sumOfFieldA | sumOfFieldB | fieldC (sumOfFieldA*sumOfFieldB)
-------------------------------------------------------------------
A | 370 | 4.4 | 1628
B | 200 | 1.5 | 300
名为 OutputRecord 的不同 POJO 将代表组合记录的每一行记录:
public class OutputRecord {
private String name;
private Integer sumOfFieldA;
private BigDecimal sumOfFieldB;
private BigDecimal fieldC;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getSumOfFieldA() {
return sumOfFieldA;
}
public void setSumOfFieldA(Integer sumOfFieldA) {
this.sumOfFieldA = sumOfFieldA;
}
public BigDecimal getSumOfFieldB() {
return sumOfFieldB;
}
public void setSumOfFieldB(BigDecimal sumOfFieldB) {
this.sumOfFieldB = sumOfFieldB;
}
public BigDecimal getFieldC() {
return fieldC;
}
public void setFieldC(BigDecimal fieldC) {
this.fieldC = fieldC;
}
}
将 InputRecords 列表转换为 OutputRecords 列表有哪些好的方法/解决方案?
我正在查看以下链接是否会有所帮助,但我在尝试将 fieldA 和 fieldB 的收集器放在一起以形成 fieldC 的新收集器时遇到了困难:
Java 8 Stream: groupingBy with multiple Collectors
Collector<InputRecord, ?, Integer> fieldACollector = Collectors.summingInt(InputRecord::getFieldA);
Collector<InputRecord, ?, BigDecimal> fieldBCollector = Collectors.reducing(BigDecimal.ZERO, InputRecord::getFieldB, BigDecimal::add);
List<Collector<InputRecord, ?, ?>> collectors = Arrays.asList(fieldACollector, fieldBCollector); // need a fieldCCollector object in the list
collectors 对象随后将用于创建 complexCollector 对象(根据 Tagir Valeev 在上述链接中接受的答案)。
【问题讨论】:
-
既然可以即时计算,为什么还需要
fieldC? -
您能否提供有关您的 POJO 的更多信息?它是可变的吗?它有吸气剂吗?构造函数是什么样的?
-
谢谢我添加了更多信息。 POJO 可以是可变的
-
感谢 Holger,我已经添加了实际问题 :)
标签: java java-8 java-stream