将 Stream 映射到包含 Total 的对象列表

Posted

技术标签:

【中文标题】将 Stream 映射到包含 Total 的对象列表【英文标题】:Map Stream to List of Objects With Total 【发布时间】:2021-09-24 21:23:16 【问题描述】:

我有一个 Map 是从这段代码中得到的

Map<String, Long> countsMap = sampleObjectList.stream()
        .collect(Collectors.groupingBy(sampleObject::getStatus, Collectors.counting()));

获取地图后,我需要创建一个对象列表,其中包含每个状态的计数和总计数。

我使用下面的 for 循环执行此操作的正常方式。

List<ObjectCountDTO> dtoList = new ArrayList<>();
long allCount = 0L;
for(Map.Entry<String, Long> entry : countsMap.entrySet()) 
    long count = entry.getValue();
    allCount += count;
    dtoList.add(new ObjectCountDTO(entry.getKey(), count)); 

dtoList.add(new ObjectCountDTO("ALL", allCount));

有没有办法在 java 8 中使用流来做到这一点?

【问题讨论】:

【参考方案1】:

你可以stream频率entrySetMap

List<ObjectCountDTO> dtoList = countsMap.entrySet().stream()
 .map(e -> new ObjectCountDTO(e.getKey(), e.getValue()).collect(Collectors.toList());
dtoList.add(new ObjectCountDTO("ALL", 
       countsMap.values().stream().mapToLong(i->i).sum()));

【讨论】:

是的,这将是正确的,但我在想是否存在仅使用 1 个流的解决方案。如果除了使用超过 1 个流没有其他解决方案,那么只使用 1 个 for 循环不是更好吗? 流并不总是最合适的工具。在这种情况下,使用 for 循环是最高效的。【参考方案2】:

如果你想在一个流中做所有事情,你可以使用下面的代码 sn-p

List<ObjectCountDTO> dtoList = new ArrayList<>();
dtoList.add(new ObjectCountDTO("ALL", countsMap.entrySet().stream()
        .map(e -> 
            dtoList.add(new ObjectCountDTO(e.getKey(), e.getValue()));
            return e;
        )
        .map(e -> e.getValue())
        .reduce(0L, (a, b) -> a + b)));

【讨论】:

以上是关于将 Stream 映射到包含 Total 的对象列表的主要内容,如果未能解决你的问题,请参考以下文章

将两个字段映射到一个数据库列

JAVA8:将对象列表映射到String [] [重复]

如何将额外的列添加到包含前一列百分比的选择语句

Java HashMap原理

JPA 将 java.io.File 或 java.nio.file.Path 对象映射到 STRING 列

将 Total 列添加到 Dynamic SQL pivot