更好的方式做流sum?



我有一个对象

public class Sample {
private String Id;
...
private String acct;
private BigDecimal amt1;
private BigDecimal amt3;
}

我有一个列表

Id | acct  |  amt1   |  amt2   
1  |  1111  |  0.50   |  0.50 
2  |  1112  |  0.50   |  0.50 

我想对列表

中的amt1和amt2求和
Map<Object, Sample> map = collectedTxs.stream()
.collect(Collectors.toMap(
f -> f.getAcct(),
Function.identity(),
(s, a) -> new Sample(
s.getId(),
s.getAcct(),
s.getAmt1().add(a.getAmt1()),
s.getAmt2().add(a.getAmt2()),
), LinkedHashMap::new));

有更好的方法吗?我不想把结果重新赋值给另一个Sample对象。

我不想将结果重新分配给另一个Sample对象。

流用于映射值。在流环境之外修改现有状态是不明智的,因为它可能在某些情况下导致数据不一致。但是您仍然可以使用Java 8+ map特性非常有效地完成此任务。(流并不总是最好或最有效的操作数据的方式。使用循环没有任何问题。)

我是这样做的。下面是类定义,唯一的变化是。

  • 一个静态复制方法,返回一个被复制的实例(根据m.c.o nemperor的建议)。
  • 添加值并返回当前实例的add方法。
static class Sample {
private String Id;
private String acct;
private BigDecimal amt1;
private BigDecimal amt2;
public Sample(String id, String acct, BigDecimal amt1,
BigDecimal amt2) {
Id = id;
this.acct = acct;
this.amt1 = amt1;
this.amt2 = amt2;   
}

public Sample(Sample sample) {
this(sample.Id, sample.acct,sample.amt1,sample.amt2);
}

public static Sample copyOf(Sample s) {
return new Sample(s.Id, s.acct, s.amt1,s.amt2);
}

public Sample add(Sample sample) {
amt1 = amt1.add(sample.amt1);
amt2 = amt2.add(sample.amt2);
return this;
}
// other getters and setters
public void setId(String id) {
Id = id;
}

public void setAcct(String acct) {
this.acct = acct;
}

public void setAmt1(BigDecimal amt1) {
this.amt1 = amt1;
}

public void setAmt2(BigDecimal amt2) {
this.amt2 = amt2;
}

public String getId() {
return Id;
}

public String getAcct() {
return acct;
}

public BigDecimal getAmt1() {
return amt1;
}

public BigDecimal getAmt2() {
return amt2;
}
@Override
public String toString() {
return String.format("[%s, %s, %s, %s]", Id, acct, amt1,
amt2);
}

}

List<Sample> collectedTxs = List.of(
new Sample("1", "1111", new BigDecimal(".50"),
new BigDecimal(".50")),
new Sample("2", "1112", new BigDecimal(".50"),
new BigDecimal(".50")),
new Sample("2", "1112", new BigDecimal("1.50"),
new BigDecimal("2.50")),
new Sample("1", "1111", new BigDecimal("4.50"),
new BigDecimal("8.50")));

流程

  • 遍历帐户列表。
  • ,并使用合并方法合并相同的帐户。
  • 帐号为key
  • s是每个帐户的第一个遇到实例。
  • BiFunction通过添加使用方法引用
  • 将它们组合在一起
Map<String,Sample> map = new HashMap<>();
for (Sample s : collectedTxs) {
map.merge(s.getAcct(), s, Sample::add);
}

map.forEach((k,v)-> System.out.println(k + " " + v);

打印

1112 [2, 1112, 2.00, 3.00]
1111 [1, 1111, 5.00, 9.00]

这是原始数据。注意,迭代中遇到的第一个帐户被更改了。

collectedTxs.forEach(System.out::println);
[1, 1111, 5.00, 9.00]
[2, 1112, 2.00, 3.00]
[2, 1112, 1.50, 2.50]
[1, 1111, 4.50, 8.50]

如果您想保留原始实例。然后在映射构造中进行以下更改。

map.merge(s.getAcct(),  Sample.copyOf(s), Sample::add);

最新更新