如何使用Java Collectors.groupingBy按最近15天对数据分组
解决方案
你原有逻辑的问题在于,直接对每个Tweet的创建日期减15天作为分组key,每个元素的key是独立计算的,无法匹配你预期的「以区间内最新日期为key、所有该日期往前15天内的数据归为一组」的规则。
实现思路
- 先把所有Tweet按创建日期倒序排序,最新的内容排在最前面
- 遍历排序后的列表,动态生成分组key:
- 首个元素的日期作为第一个分组key
- 后续元素如果和当前分组key的日期间隔≤15天,归入当前分组
- 间隔超过15天时,以当前元素的日期作为新的分组key
- 最终得到的Map的key就是你要的每个分组的最新日期,value是对应分组的所有Tweet
完整代码
import java.time.LocalDate; import java.time.temporal.ChronoUnit; import java.util.*; import java.util.stream.Collectors; public class Tweet { private String id; private LocalDate createdAt; public Tweet(String id, LocalDate createdAt) { this.id = id; this.createdAt = createdAt; } public String getId() { return id; } public LocalDate getCreatedAt() { return createdAt; } @Override public String toString() { return "Tweet(\"" + id + "\", \"" + createdAt + "\")"; } public static void main(String[] args) { List<Tweet> tweets = new ArrayList<>(){{ add(new Tweet("1", LocalDate.of(2021,11,17))); add(new Tweet("2", LocalDate.of(2021,11,16))); add(new Tweet("3", LocalDate.of(2021,11,14))); add(new Tweet("4", LocalDate.of(2021,11,13))); add(new Tweet("5", LocalDate.of(2021,11,12))); add(new Tweet("7", LocalDate.of(2021,10,9))); add(new Tweet("8", LocalDate.of(2021,10,8))); add(new Tweet("9", LocalDate.of(2021,10,7))); add(new Tweet("10", LocalDate.of(2021,9,2))); add(new Tweet("11", LocalDate.of(2021,9,1))); }}; // 按创建日期倒序排序 List<Tweet> sortedTweets = tweets.stream() .sorted(Comparator.comparing(Tweet::getCreatedAt).reversed()) .toList(); Map<LocalDate, List<Tweet>> groupResult = new LinkedHashMap<>(); LocalDate currentGroupKey = null; for (Tweet tweet : sortedTweets) { if (currentGroupKey == null) { currentGroupKey = tweet.getCreatedAt(); groupResult.put(currentGroupKey, new ArrayList<>()); } long daysDiff = ChronoUnit.DAYS.between(tweet.getCreatedAt(), currentGroupKey); if (daysDiff <= 15) { groupResult.get(currentGroupKey).add(tweet); } else { currentGroupKey = tweet.getCreatedAt(); groupResult.put(currentGroupKey, new ArrayList<>()); groupResult.get(currentGroupKey).add(tweet); } } // 打印结果 groupResult.forEach((key, value) -> { System.out.println(key + ": "); value.forEach(tweet -> System.out.println(" " + tweet)); System.out.println(); }); } }
输出说明
运行代码得到的结果和你预期的效果完全一致,你示例中9月分组的key标注为2021-09-01属于笔误,实际按规则最新日期为2021-09-02,若需要调整为按区间最早日期为key,把排序规则改为升序即可。
内容的提问来源于stack exchange,提问作者Dinesh
相关产品推荐
相关产品推荐

