使用 Java 8 按间隔对 LocalDateTime 对象进行分组

Grouping LocalDateTime objects in intervals using Java 8

我有一个以下格式的列表,我想将此列表分组为分钟间隔。

 List<Item> myObjList = Arrays.asList(
                new Item(LocalDateTime.parse("2020-09-22T00:13:36")), 
                new Item(LocalDateTime.parse("2020-09-22T00:17:20")),
                new Item(LocalDateTime.parse("2020-09-22T01:25:20")),
                new Item(LocalDateTime.parse("2020-09-18T00:17:20")),
                new Item(LocalDateTime.parse("2020-09-19T00:17:20")));

例如,给定 10 分钟的间隔,列表中的前 2 个对象应在同一组中,第三个对象应在不同的组中,依此类推。

能否使用 Java 的 8 groupingBy 函数将此列表分组到区间内?

我的解决方案是将列表中的每个日期与列表中的所有其他日期进行比较,并将相差 X 分钟的日期添加到新列表中。这似乎很慢 'hacky' 解决方法,我想知道是否有更稳定的解决方案。

可以将 Collectors#groupingBy to group LocalDateTime 个对象用于 10 分钟间隔的列表中。您必须调整此代码段以与您的 Item class 一起使用,但逻辑​​是相同的。

List<LocalDateTime> myObjList = Arrays.asList(
    LocalDateTime.parse("2020-09-22T00:13:36"),
    LocalDateTime.parse("2020-09-22T00:17:20"),
    LocalDateTime.parse("2020-09-22T01:25:20"),
    LocalDateTime.parse("2020-09-18T00:17:20"),
    LocalDateTime.parse("2020-09-19T00:17:20")
);

System.out.println(myObjList.stream().collect(Collectors.groupingBy(time -> {
    // Store the minute-of-hour field.
    int minutes = time.getMinute();

    // Determine how many minutes we are above the nearest 10-minute interval.
    int minutesOver = minutes % 10;

    // Truncate the time to the minute field (zeroing out seconds and nanoseconds),
    // and force the number of minutes to be at a 10-minute interval.
    return time.truncatedTo(ChronoUnit.MINUTES).withMinute(minutes - minutesOver);
})));

输出

{
    2020-09-22T00:10=[2020-09-22T00:13:36, 2020-09-22T00:17:20],
    2020-09-19T00:10=[2020-09-19T00:17:20],
    2020-09-18T00:10=[2020-09-18T00:17:20],
    2020-09-22T01:20=[2020-09-22T01:25:20]
}

您没有为组指定密钥,所以我只是使用 (minutes/10)*10 的商来获取标记到时间截断为小时的分钟范围的开始。

List<Item> myObjList = Arrays.asList(
        new Item(LocalDateTime.parse("2020-09-22T00:13:36")),
        new Item(LocalDateTime.parse("2020-09-22T00:17:20")),
        new Item(LocalDateTime.parse("2020-09-22T01:25:20")),
        new Item(LocalDateTime.parse("2020-09-18T00:17:20")),
        new Item(LocalDateTime.parse("2020-09-19T00:17:20")));

Map<String, List<Item>> map = myObjList.stream()
        .collect(Collectors.groupingBy(item -> {
            int range =
                    (item.getTime().getMinute() / 10) * 10;
            return item.getTime()
                    .truncatedTo(ChronoUnit.HOURS).plusMinutes(range) +
                    " - " + (range + 9) + ":59";
        }));

        
map.entrySet().forEach(System.out::println);

版画

2020-09-22T00:10 - 19:59=[2020-09-22T00:13:36, 2020-09-22T00:17:20]
2020-09-19T00:10 - 19:59=[2020-09-19T00:17:20]
2020-09-18T00:10 - 19:59=[2020-09-18T00:17:20]
2020-09-22T01:20 - 29:59=[2020-09-22T01:25:20]

这是我用的class

class Item {
    LocalDateTime ldt;
    
    public Item(LocalDateTime ldt) {
        this.ldt = ldt;
    }
    
    public String toString() {
        return ldt.toString();
    }
    
    public LocalDateTime getTime() {
        return ldt;
    }
}