使用Java 8 Streams的收集器根据现有键/值对增加值

时间:2019-06-14 16:02:11

标签: java java-8 functional-programming java-stream

假设有一个List<Object>,并且Object包含两种方法:getUserIdgetPoints

考虑List<Object>包含三个对象,并且它们包含以下数据:

userId A; 3 points
userId A; 5 points
userId B; 1 point

在正确收集了此信息之后,我期望有一个Map<String, Integer>如下所示:

A: 8,
B: 1

我正在尝试使用Java的8个功能接口(流)进行此操作,因为我只需要最终结果,而在它们之间也不需要任何映射。如果没有其他方法,我愿意对此进行修改。 我首先想到了这个:

this.service.getListObject()
    .stream()
    .collect(Collectors.toMap(Object::getUserId, Object::getPoints));

但是,这显示不足,因为它将始终用最新值替换密钥,从而产生:

A: 5,
B: 1

如何调整Collectors.toMap()中的最后几位以根据已存储在映射中的值自动增加其值,以便产生上面的结果?

2 个答案:

答案 0 :(得分:6)

Collectors.groupingByCollectors.summingInt一起用作下游收集器:

this.service.getListObject()
    .stream().collect(Collectors.groupingBy(
        Object::getUserId, Collectors.summingInt(Object::getPoints)));

答案 1 :(得分:4)

要更正您刚开始的实现,您需要一个合并功能,如下:

...stream().collect(Collectors.toMap(CustomObject::getUserId, 
                    CustomObject::getPoints, Integer::sum)); // <--- summing value here

最终也可以用groupingBysummingInt的组合来表示。