java - 收集器嵌套分组依据与多个字段

标签 java spring java-stream collectors

您将如何使用收集器在第 2 层按多个字段进行分组。例如:

"someList": {
        "firstLevelElementX": {
              "secondLevelElementW": 2,
              "secondLevelElementZ": 3,
              "secondLevelElementK": 7
        },
        "firstLevelElementY": {
              "secondLevelElementW": 1,
              "secondLevelElementZ": 3,
              "secondLevelElementK": 10
        }
}

我试图用“secondLevel”元素创建一个类,并按这个类分组,但无法让它工作:

@Data
@AllArgsConstructor
public class someClass{
    private String firstLevelElement;
    private Long secondLevelElementW;
    private Long secondLevelElementZ;
    private Long secondLevelElementK= 0L;

}

我就是这样做的:

Map<String,Map<String,Long>> someList =
            events.stream().collect(
                Collectors.groupingBy(
                    someDAO::getFirstLevelElement,
                    Collectors.groupingBy(
                        someClass::getSecondLevelFields,
                        Collectors.counting())
                )
            );

有一些解决方案建议使用 n 级分组(使用链),但我更愿意尽可能使其不那么复杂和更简洁。

编辑

我会尝试提供一个更好的例子来阐明我自己,这是我的列表:

{
      "date": "2019-04-08 08:28:01.0",
      "source": "maint",
      "severity": "HARMLESS",
      "site": "USA",
      "hostname": "usaHost"
    },
    {
      "date": "2019-04-08 08:28:01.0",
      "source": "CPU_Checker",
      "severity": "MINOR",
      "site": "GERMANY",
      "hostname": "germanyHost"
    },
    {
      "date": "2019-04-02 08:28:01.0",
      "source": "maint",
      "severity": "HARMLESS",
      "site": "USA",
      "hostname": "anotherUsaHost"
    }

我想在第二级对“来源”和“严重性”使用分组依据,因此输出应如下所示:

"eventList": {
        "USA": {
              "maint": 2,
              "HARMLESS": 2
        },
        "GERMANY": {
              "CPU_checker": 1,
              "MINOR": 1
        }
}

最佳答案

如果您可以使用 Java 9 或更高版本,您可以使用 Collectors.flatMapping()实现这一目标:

Map<String, Map<String, Long>> eventList = list.stream()
        .collect(Collectors.groupingBy(MyObject::getSite, Collectors.flatMapping(
                o -> Stream.of(o.getSource(), o.getSeverity()),
                Collectors.groupingBy(Function.identity(), Collectors.counting())
        )));

结果是这样的:

{
    USA={maint=2, HARMLESS=2}, 
    GERMANY={CPU_Checker=1, MINOR=1}
}

如果您不能使用 Java 9,您可以自己实现 flatMapping() 函数。你可以看看Java 9 Collectors.flatMapping rewritten in Java 8 ,这应该可以帮助您。

关于java - 收集器嵌套分组依据与多个字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55608520/

相关文章:

java - 是否可以使用 th-field 来检索 Thymeleaf 中列表的值?

java - 如何制作一个无法退出的app

java - Spring MVC - 如何在 Rest Controller 中以 JSON 形式返回简单字符串

java - 使用并行流到 FileWriter 可以吗?

java - 将对象传递给方法并更改属性

java - 尝试从继承的角度理解转换和动态绑定(bind)

java - 串流意外结束

java - 如何编写从tomcat运行的java批处理

java - 将 List<Map<Long, String>> 转换为 List<Long> Java 8

java - Stream() 方法是惰性方法吗?如果是惰性的,那么这个方法本身可以被认为是中间方法,因为它返回一个流吗?