您将如何使用收集器以便在第二级按多个字段分组.例如:
"someList": {
"firstLevelElementX": {
"secondLevelElementW": 2,"secondLevelElementZ": 3,"secondLevelElementK": 7
},"firstLevelElementY": {
"secondLevelElementW": 1,"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","hostname": "anotherUsaHost"
}
我想在第二级上对“源”和“严重性”使用分组依据,因此输出应如下所示:
"eventList": {
"USA": {
"maint": 2,"HARMLESS": 2
},"GERMANY": {
"cpu_checker": 1,"MINOR": 1
}
}
最佳答案
如果可以使用Java 9或更高版本,则可以使用
Collectors.flatMapping()
来实现:
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,这应该会对您有所帮助.