Java 流 : Grouping and counting by multiple fields

标签 java java-8 java-stream

我有以下对象:

class Event {
private LocalDateTime when;
private String what;

public Event(LocalDateTime when, String what) {
  super();
  this.when = when;
  this.what = what;
}

public LocalDateTime getWhen() {
  return when;
}

public void setWhen(LocalDateTime when) {
  this.when = when;
}

public String getWhat() {
  return what;
}

public void setWhat(String what) {
  this.what = what;
}

我需要按年/月 (yyyy-mm) 和事件类型进行汇总,然后进行计数。例如下面的列表

List<Event> events = Arrays.asList(
  new Event(LocalDateTime.parse("2017-03-03T09:01:16.111"), "EVENT1"),
  new Event(LocalDateTime.parse("2017-03-03T09:02:11.222"), "EVENT1"),
  new Event(LocalDateTime.parse("2017-04-03T09:04:11.333"), "EVENT1"), 
  new Event(LocalDateTime.parse("2017-04-03T09:04:11.333"), "EVENT2"),
  new Event(LocalDateTime.parse("2017-04-03T09:06:16.444"), "EVENT2"),
  new Event(LocalDateTime.parse("2017-05-03T09:01:26.555"), "EVENT3")
);

应该产生以下结果:

Year/Month  Type  Count
2017-03     EVENT1    2  
2017-04     EVENT1    1
2017-04     EVENT2    2
2017-04     EVENT3    1

知道我是否可以(如果可以,如何)使用 Streams API 实现它?

最佳答案

如果你不想创建一个新的键类,正如 assylias 所建议的,你可以做一个双 groupingBy

Map<YearMonth,Map<String,Long>> map = 
     events.stream()
           .collect(Collectors.groupingBy(e -> YearMonth.from(e.getWhen()),
                    Collectors.groupingBy(x -> x.getWhat(), Collectors.counting()))
                   );

...后跟嵌套打印

map.forEach((k,v)-> v.forEach((a,b)-> System.out.println(k + " " +  a + " " + b)));

这打印

2017-05 EVENT3 1
2017-04 EVENT2 2
2017-04 EVENT1 1
2017-03 EVENT1 2

编辑:我注意到日期的顺序与 OP 的预期解决方案相反。使用 groupingBy 的 3 参数版本,您可以指定一个排序的映射实现

Map<YearMonth,Map<String,Long>> map = 
     events.stream()
           .collect(Collectors.groupingBy(e -> YearMonth.from(e.getWhen()), TreeMap::new, 
                    Collectors.groupingBy(x -> x.getWhat(), Collectors.counting()))
                   );

现在打印相同的 map.forEach(...)

2017-03 EVENT1 2
2017-04 EVENT2 2
2017-04 EVENT1 1
2017-05 EVENT3 1

关于Java 流 : Grouping and counting by multiple fields,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43611552/

相关文章:

java - 如何查找 Netbeans 用于运行应用程序的命令

java - 如果应用程序关闭并重新打开,动态创建的图像按钮即使在使用后也为空

java - 如何从 Java Streams 中的列表创建 Map 的组合键

java - 从流中收集到多图

java - 如何使用流获取多个属性具有最大值的对象?

java - 从 Arduino 读取数据到处理中返回空结果

java - 如何在Jsoup中删除部分网页?

maven - ANTLR4生成的代码未编译: “cannot override reset()”

java - 如何运行单一场景

java - 如何仅从所需的类(流)获取数据?