流式采集然后获取最新记录求和一个值
Stream collectingAndThen get latest record to sum a value
目前,我正面临以下数据集。我的目标是通过前两列获得 Column4 组的 最新 总和。
// Column5 = version
new Foo(1, "bbb", "cccc", 111, 0)
new Foo(1, "bbb", "cccc", 234, 1) // latest
new Foo(1, "bbb", "dddd", 111, 0)
new Foo(1, "bbb", "dddd", 112, 1)
new Foo(1, "bbb", "dddd", 113, 2)
new Foo(1, "bbb", "dddd", 114, 3) // latest
new Foo(1, "xxx", "cccc", 111, 0) // latest
new Foo(2, "xxx", "yyyy", 0, 0)
new Foo(2, "xxx", "yyyy", 1, 1) // latest
...
我试过的是
// key: Column1, key: Column2, value: latest sum of Column4
Map<Long, Map<String, Integer>> fooMap = fooList.stream().collect(
Collectors.groupingBy(Foo::getColumn1, Collectors.groupingBy(Foo::getColumn2,
Collectors.collectingAndThen(????))));
我试过 ????
部分是否 Collectors.groupingBy
、Collectors.maxBy
、Collectors.summingInt
但总是错的。
我理想中的地图应该是这样的:
1->bbb->348
,1->xxx->111
,2->xxx->1
.
请帮忙告诉我是否有任何补充。谢谢。
您可以通过以下方式获得它:
Map<Long, Map<String, Integer>> fooMap = fooList.stream().collect(
groupingBy(Foo::getColumn1,
groupingBy(Foo::getColumn2,
collectingAndThen(
groupingBy(Foo::getColumn3,
collectingAndThen(
maxBy(comparing(Foo::getVersion)),
Optional::get
)),
m -> m.values().stream().mapToInt(Foo::getColumn4).sum()
)
)
));
首先按column1和column2分组,然后我们使用collectingAndThen
按column3分组,因为我们要post处理它。
按 column3 分组我们想按版本获取最大值,我们使用另一个 collectingAndThen
,因为 maxBy 创建和 Optional
,所以我们应用一个 Optional::Get
得到一个 Map<String, Foo>
而不是 Map<String, Optional<Foo>>
.
post过程是对map中Foo的所有column4求和,也就是最大版本的。
将简化模型表示为:
record Foo(Long one, String two, String three, int value, int version) {
}
record Result(Long one, String two, int totalValue) {
}
您可以从按前三个属性分组并将值映射到选择最大版本的身份开始。
Map<List<Object>, Foo> groupedMaxVersion = fooList.stream()
.collect(Collectors.toMap(foo -> Arrays.asList(foo.one(), foo.two(), foo.three()),
foo -> foo, BinaryOperator.maxBy(Comparator.comparing(Foo::version))));
这之后可能是您根据第 4 列中的值查找的下游求和:
Map<List<Object>, Integer> resultMapping = groupedMaxVersion.entrySet().stream()
.collect(Collectors.groupingBy(e -> Arrays.asList(e.getKey().get(0), e.getKey().get(1)),
Collectors.summingInt(e -> e.getValue().value())));
此外,您只需根据需要将其框入结果数据结构即可
resultMapping.entrySet().stream()
.map(e -> new Result((Long) e.getKey().get(0), (String) e.getKey().get(1), e.getValue()))
.collect(Collectors.toList());
目前,我正面临以下数据集。我的目标是通过前两列获得 Column4 组的 最新 总和。
// Column5 = version
new Foo(1, "bbb", "cccc", 111, 0)
new Foo(1, "bbb", "cccc", 234, 1) // latest
new Foo(1, "bbb", "dddd", 111, 0)
new Foo(1, "bbb", "dddd", 112, 1)
new Foo(1, "bbb", "dddd", 113, 2)
new Foo(1, "bbb", "dddd", 114, 3) // latest
new Foo(1, "xxx", "cccc", 111, 0) // latest
new Foo(2, "xxx", "yyyy", 0, 0)
new Foo(2, "xxx", "yyyy", 1, 1) // latest
...
我试过的是
// key: Column1, key: Column2, value: latest sum of Column4
Map<Long, Map<String, Integer>> fooMap = fooList.stream().collect(
Collectors.groupingBy(Foo::getColumn1, Collectors.groupingBy(Foo::getColumn2,
Collectors.collectingAndThen(????))));
我试过 ????
部分是否 Collectors.groupingBy
、Collectors.maxBy
、Collectors.summingInt
但总是错的。
我理想中的地图应该是这样的:
1->bbb->348
,1->xxx->111
,2->xxx->1
.
请帮忙告诉我是否有任何补充。谢谢。
您可以通过以下方式获得它:
Map<Long, Map<String, Integer>> fooMap = fooList.stream().collect(
groupingBy(Foo::getColumn1,
groupingBy(Foo::getColumn2,
collectingAndThen(
groupingBy(Foo::getColumn3,
collectingAndThen(
maxBy(comparing(Foo::getVersion)),
Optional::get
)),
m -> m.values().stream().mapToInt(Foo::getColumn4).sum()
)
)
));
首先按column1和column2分组,然后我们使用collectingAndThen
按column3分组,因为我们要post处理它。
按 column3 分组我们想按版本获取最大值,我们使用另一个 collectingAndThen
,因为 maxBy 创建和 Optional
,所以我们应用一个 Optional::Get
得到一个 Map<String, Foo>
而不是 Map<String, Optional<Foo>>
.
post过程是对map中Foo的所有column4求和,也就是最大版本的。
将简化模型表示为:
record Foo(Long one, String two, String three, int value, int version) {
}
record Result(Long one, String two, int totalValue) {
}
您可以从按前三个属性分组并将值映射到选择最大版本的身份开始。
Map<List<Object>, Foo> groupedMaxVersion = fooList.stream()
.collect(Collectors.toMap(foo -> Arrays.asList(foo.one(), foo.two(), foo.three()),
foo -> foo, BinaryOperator.maxBy(Comparator.comparing(Foo::version))));
这之后可能是您根据第 4 列中的值查找的下游求和:
Map<List<Object>, Integer> resultMapping = groupedMaxVersion.entrySet().stream()
.collect(Collectors.groupingBy(e -> Arrays.asList(e.getKey().get(0), e.getKey().get(1)),
Collectors.summingInt(e -> e.getValue().value())));
此外,您只需根据需要将其框入结果数据结构即可
resultMapping.entrySet().stream()
.map(e -> new Result((Long) e.getKey().get(0), (String) e.getKey().get(1), e.getValue()))
.collect(Collectors.toList());