Java - Collectors.groupingBy - 最近 15 天

Java - Collectors.groupingBy - the last 15 days

是否可以使用 Java 的 Collectors.groupingBy 按过去 15 天分组?

输入:

public class Tweet { 

 String id;
 LocalDate createdAt; 

 // Constructor Ignored

 List<Tweet> tweets = new ArrayList(){{
  add(new Tweet("1", "2021-11-17"));
  add(new Tweet("2", "2021-11-16"));
  add(new Tweet("3", "2021-11-14"));
  add(new Tweet("4", "2021-11-13"));
  add(new Tweet("5", "2021-11-12"));
  add(new Tweet("7", "2021-10-09"));
  add(new Tweet("8", "2021-10-08"));
  add(new Tweet("9", "2021-10-07"));
  add(new Tweet("10", "2021-09-02"));
  add(new Tweet("11", "2021-09-01"));
 ...

 }};

}

预期输出:

2021-11-17:  (group must include 2021-11-17 + 15 days before 17th)
 Tweet("1", "2021-11-17");
 Tweet("2", "2021-11-16");
 Tweet("3", "2021-11-14");
 Tweet("4", "2021-11-13");
 Tweet("5", "2021-11-12");

2021-10-09: (group to include 2021-10-09 + 15 days before 9th)
 Tweet("7", "2021-10-09");
 Tweet("8", "2021-10-08");
 Tweet("9", "2021-10-07");

2021-09-01: (group to include 2021-09-01 + 15 days before 1st)
Tweet("10", "2021-09-02");
Tweet("11", "2021-09-01");

当前逻辑(不工作):

主要方法:


TemporalAdjusters adjuster = TemporalAdjusters.ofDateAdjuster(d -> d.minusDays(15));

Map<LocalDate, List<Tweets>> groupByLast15Days = tweets.stream()
                .collect(Collectors.groupingBy(item -> item.createdAt())
                  .with(adjuster)));

System.out.println(groupByLast15Days);  // provides incorrect results

非常感谢任何帮助!谢谢!

您可以使用 ChronoUnit.DAYS.between(from,to) 获得两个 LocalDateTime 之间的日期差异,如 here 所述。

然后您可以将其除以 15(因此该范围内的所有天数都相同):

LocalDate origin=LocalDate.now();
Map<LocalDate, List<Tweets>> groupByLast15Days = tweets.stream()
    .collect(Collectors.groupingBy(item-> 
       Long.valueOf(ChronoUnit.DAYS.between(item.createdAt(),origin)/15));

如果要按开始日期分组,可以逆向计算(而15天之间的差异被整数除法消除):

LocalDate origin=LocalDate.now();
Map<LocalDate, List<Tweets>> groupByLast15Days = tweets.stream()
    .collect(Collectors.groupingBy(item -> 
        origin.plusDays(
            (ChronoUnit.DAYS.between(origin, item.createdAt()) /15)*15
        )
    ));

如果你想使用TemporalAdjusters,你可以这样做:

LocalDate origin=LocalDate.now();
TemporalAdjusters adjuster = TemporalAdjusters.ofDateAdjuster(d ->
    origin.plusDays(
        (ChronoUnit.DAYS.between(origin, d) /15)*15
    )
);

解释:

一个整数除以另一个整数总是得到一个整数,即使商有小数位。整数除法只是删除那些小数位。如果您将一个数字除以 15,它将 return 15 个连续数字的结果相同。再次乘以 15 后,您将得到这 15 个数字中的第一个。将一个数字除以 15 再乘以 15 的目的是每 15 个连续的数字设置为相同的数字(这 15 个中的第一个)。

ChronoUnit.DAYS.between(date1, date2)只是计算date1date2之间的天数。