减去 java 8 中每个组的值

Subtract the values for each group in java 8

我有 class Data10,它有 5 个字段并有值列表,然后我想从 valuePeriod 的每个唯一 ID 组中减去值,如下例所示,最后在结果中生成具有相同 ID 的新 Data10 对象, 同年, 新名称, 相同的 valuePeriod 和减值结果.

注意:在下面的例子中,我只有 2 个名字,我想从 A-B 中减去它们,然后名字在预期结果中变成“C”。

重要说明:我想做 A-B 而不是 B-A。

class Data10 {
    int id;
    int year;
    String name;
    int valuePeriod;
    BigDecimal value;
}


List<Data10> list = new ArrayList();
list.add(new Data10(1, 2020, "A", 1, new BigDecimal(5.5)));
list.add(new Data10(1, 2020, "B", 1, new BigDecimal(2.5)));
list.add(new Data10(1, 2020, "A", 2, new BigDecimal(8.5)));
list.add(new Data10(1, 2020, "B", 2, new BigDecimal(1.5)));
list.add(new Data10(1, 2020, "A", 3, new BigDecimal(6.5)));
list.add(new Data10(1, 2020, "B", 3, new BigDecimal(2.5)));

list.add(new Data10(2, 2020, "A", 1, new BigDecimal(6.5)));
list.add(new Data10(2, 2020, "B", 1, new BigDecimal(1.5)));
list.add(new Data10(2, 2020, "A", 2, new BigDecimal(9.5)));
list.add(new Data10(2, 2020, "B", 2, new BigDecimal(3.5)));
list.add(new Data10(2, 2020, "A", 3, new BigDecimal(7.5)));
list.add(new Data10(2, 2020, "B", 3, new BigDecimal(5.5)));

我尝试对数据进行分组,但如何减去相同 valuePeriod 的值然后生成新对象?请任何帮助。提前致谢!

list.stream().collect(Collectors.groupingBy(Data10::getId, Collectors.groupingBy(Data10::getValuePeriod)));

预期结果:

Data10(1, 2020, "C", 1, 3.0);  (Subtract the value for same valuePeriod A-B)
Data10(1, 2020, "C", 2, 7.0);
Data10(1, 2020, "C", 3, 4.0);

Data10(2, 2020, "C", 1, 5.0);
Data10(2, 2020, "C", 2, 6.0);
Data10(2, 2020, "C", 3, 2.0);

如果我能想到更好的方法,我会post。但目前这是一个两个阶段的过程。

  • 首先使用名称、id、valuePeriod 和年份作为键创建一个地图。这假定每个 A 都有一个匹配的 B(否则它会变得更复杂)。
Map<String, Data10> map =
        list.stream()
                .collect(Collectors.toMap(
                        d -> d.getName() + d.getId()
                                + d.getValuePeriod()+d.getYear(),
                        d -> d));

map.entrySet().forEach(System.out::println);

打印

A112020=[1, 2020, A, 1, 5.5]
A222020=[2, 2020, A, 2, 9.5]
A232020=[2, 2020, A, 3, 7.5]
A122020=[1, 2020, A, 2, 8.5]
A132020=[1, 2020, A, 3, 6.5]
B212020=[2, 2020, B, 1, 1.5]
B222020=[2, 2020, B, 2, 3.5]
B112020=[1, 2020, B, 1, 2.5]
B232020=[2, 2020, B, 3, 5.5]
A212020=[2, 2020, A, 1, 6.5]
B132020=[1, 2020, B, 3, 2.5]
B122020=[1, 2020, B, 2, 1.5]
  • 现在流式传输原始列表并使用映射引用适当的键,过滤掉“B”值。
  • 创建一个新的 Data10 实例,填充现有值以及 A-B
  • 的差异

List<Data10> result = list.stream().filter(d->d.getName().equals("A"))
        .map(d->new Data10(d.getId(),
               d.getYear(), "C", d.getValuePeriod(),
                     map.get("A" + d.getId() + d.getValuePeriod()+d.getYear()).getValue()
                             .subtract(map.get("B" + d.getId()
                        + d.getValuePeriod()+d.getYear()).getValue())))
        .toList();

result.forEach(System.out::println);

打印

[1, 2020, C, 1, 3.0]
[1, 2020, C, 2, 7.0]
[1, 2020, C, 3, 4.0]
[2, 2020, C, 1, 5.0]
[2, 2020, C, 2, 6.0]
[2, 2020, C, 3, 2.0]

我假设可能有不同的年份可能具有相同的 valuePeriod,因此有必要将其包含在密钥中以定位适当的值。您当然可以修改以满足您的具体要求。