如何使用Java Stream API(groupingBy collector)对列表中的值进行分组?

vvv*_*vvv 7 java datetime date java-stream java-date

我有Entry对象列表.Entry是一个:

class Entry {
   private final Date date;
   private final String value;

   // constructor
   // getters
}
Run Code Online (Sandbox Code Playgroud)

我需要在白天对这些条目进行分组.例如,

2011-03-21 09:00 VALUE1
2011-03-21 09:00 VALUE2
2011-03-22 14:00 VALUE3
2011-03-22 16:00 VALUE4
2011-03-21 16:00 VALUE5
Run Code Online (Sandbox Code Playgroud)

应分组:

2011-03-21
    VALUE1
    VALUE2
    VALUE5

2011-03-22
    VALUE3
    VALUE4
Run Code Online (Sandbox Code Playgroud)

我想得到一个Map<Date, List<Entry>>.如何使用Stream API(groupingBy collector)获取此信息?

我的尝试如下:

final Map<Date, List<Entry>> entries =
        list.stream().collect(Collectors.groupingBy(request -> {
        final Calendar ogirinal = Calendar.getInstance();
        ogirinal.setTime(request.getDate());

        final Calendar cal = Calendar.getInstance();
        cal.set(Calendar.DAY_OF_MONTH, ogirinal.get(Calendar.DAY_OF_MONTH));
        cal.set(Calendar.MONTH, ogirinal.get(Calendar.MONTH));
        cal.set(Calendar.YEAR, ogirinal.get(Calendar.YEAR));

        return cal.getTime();
    }));
Run Code Online (Sandbox Code Playgroud)

输出:

2011-03-21
    VALUE1
2011-03-21
    VALUE2
2011-03-22
    VALUE3
    VALUE4
2011-03-21
    VALUE5
Run Code Online (Sandbox Code Playgroud)

Lar*_*ner 14

您必须截断日期值,因为它们可能在毫秒之间不同:

import static java.time.temporal.ChronoUnit.DAYS;

final Map<Instant, List<Entry>> entries =
    list.stream().collect(Collectors.groupingBy(request -> 
        request.getDate().toInstant().truncatedTo(DAYS)));
Run Code Online (Sandbox Code Playgroud)


Jua*_*oza 10

再次不明白为什么你在使用java.util.Date时可以使用LocalDateTime例如.但这是我的尝试:

Map<Date, List<Entry>> entries = list.stream().collect(Collectors.groupingBy(e ->
    // easier way to truncate the date
    Date.from(e.getDate().toInstant().truncatedTo(ChronoUnit.DAYS)))
);
Run Code Online (Sandbox Code Playgroud)

DEMO