Java新手求助:编写含嵌套对象的Review类排序算法(兼顾主对象字段)
Java新手求助:含嵌套Update对象的Review列表排序问题
问题说明
我是Java新手,需要对包含嵌套Update对象的Review类列表进行排序,排序时需同时考虑Review自身的date字段和嵌套Update的date字段。
类定义
Review类
public class Review { String date; Update update; // 为打印方便重写toString方法 @Override public String toString() { return "Review{date='" + date + "', update=" + update + "}"; } }
Update类
public class Update { String date; // 为打印方便重写toString方法 @Override public String toString() { return "Update{date='" + date + "'}"; } }
错误的排序代码
我写的排序逻辑有问题,输出不符合预期,代码如下:
import java.time.LocalDateTime; import java.util.List; import java.util.Comparator; import java.util.stream.Collectors; public class Test { public static void main(String[] args) { Review review = new Review(); Update update = new Update(); update.date = LocalDateTime.now().toString(); review.date = LocalDateTime.now().minusDays(20L).toString(); review.update = update; Review review1 = new Review(); Update update1 = new Update(); update1.date = LocalDateTime.now().minusDays(5L).toString(); review1.date = LocalDateTime.now().minusDays(30L).toString(); review1.update = update1; Review review10 = new Review(); Update update10 = new Update(); update10.date = LocalDateTime.now().minusDays(1L).toString(); review10.date = LocalDateTime.now().minusDays(100L).toString(); review10.update = update10; Review review2 = new Review(); review2.date = LocalDateTime.now().minusDays(40L).toString(); Review review3 = new Review(); review3.date = LocalDateTime.now().minusDays(50L).toString(); Review review4 = new Review(); review4.date = LocalDateTime.now().minusDays(2L).toString(); List<Review> reviews = List.of(review, review1, review2, review3, review4, review10); Comparator<Review> reviewComparator = Comparator.comparing(review5 -> review5.date); System.out.println(reviews = reviews.stream().sorted(reviewComparator.reversed()).collect(Collectors.toList())); for (int i = 0; i < reviews.size(); i++) { Review review5 = reviews.get(i); for (int z = 1; z < reviews.size(); z++) { if (z >= i) { Review review6 = reviews.get(z); if (review6.update != null) { LocalDateTime date1 = LocalDateTime.parse(review6.update.date); LocalDateTime date2 = LocalDateTime.parse(review5.date); int i1 = date1.compareTo(date2); if (i1 > 0) { reviews.remove(review6); reviews.add(i, review6); } else if (review5.update != null) { LocalDateTime date3 = LocalDateTime.parse(review6.update.date); LocalDateTime date4 = LocalDateTime.parse(review5.update.date); int i2 = date3.compareTo(date4); if (i2 > 0) { reviews.remove(review6); reviews.add(i, review6); } } } } } } System.out.println(reviews); } }
当前输出
[ Review{date='2022-10-11T13:17:01.754934500', update=Update{date='2023-01-18T13:17:01.754934500'}}, Review{date='2022-12-20T13:17:01.754934500', update=Update{date='2023-01-14T13:17:01.754934500'}}, Review{date='2022-12-30T13:17:01.754934500', update=Update{date='2023-01-19T13:17:01.753935600'}}, Review{date='2023-01-17T13:17:01.754934500', update=null}, Review{date='2022-12-10T13:17:01.754934500', update=null}, Review{date='2022-11-30T13:17:01.754934500', update=null} ]
期望输出
[ Review{date='2022-12-30T13:17:01.754934500', update=Update{date='2023-01-19T13:17:01.753935600'}}, Review{date='2022-10-11T13:17:01.754934500', update=Update{date='2023-01-18T13:17:01.754934500'}}, Review{date='2023-01-17T13:17:01.754934500', update=null}, Review{date='2022-12-20T13:17:01.754934500', update=Update{date='2023-01-14T13:17:01.754934500'}}, Review{date='2022-12-10T13:17:01.754934500', update=null}, Review{date='2022-11-30T13:17:01.754934500', update=null} ]
修正方案
原来手动调整列表元素的方式逻辑混乱,容易出错。正确做法是自定义Comparator,统一处理每个Review的排序基准:
核心逻辑
每个Review的排序依据是它的最晚日期:
- 如果Review有Update,取
Review.date和Update.date中较晚的那个 - 如果没有Update,直接用
Review.date - 按这个最晚日期倒序排列
修正后的代码
import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Comparator; import java.util.List; public class Test { public static void main(String[] args) { Review review = new Review(); Update update = new Update(); update.date = LocalDateTime.now().toString(); review.date = LocalDateTime.now().minusDays(20L).toString(); review.update = update; Review review1 = new Review(); Update update1 = new Update(); update1.date = LocalDateTime.now().minusDays(5L).toString(); review1.date = LocalDateTime.now().minusDays(30L).toString(); review1.update = update1; Review review10 = new Review(); Update update10 = new Update(); update10.date = LocalDateTime.now().minusDays(1L).toString(); review10.date = LocalDateTime.now().minusDays(100L).toString(); review10.update = update10; Review review2 = new Review(); review2.date = LocalDateTime.now().minusDays(40L).toString(); Review review3 = new Review(); review3.date = LocalDateTime.now().minusDays(50L).toString(); Review review4 = new Review(); review4.date = LocalDateTime.now().minusDays(2L).toString(); // 用ArrayList替代List.of,避免不可变列表的问题 List<Review> reviews = new ArrayList<>(List.of(review, review1, review2, review3, review4, review10)); // 自定义Comparator Comparator<Review> reviewComparator = (r1, r2) -> { // 获取r1的最晚日期 LocalDateTime r1Latest = getLatestDate(r1); // 获取r2的最晚日期 LocalDateTime r2Latest = getLatestDate(r2); // 倒序排列,所以用r2Latest.compareTo(r1Latest) return r2Latest.compareTo(r1Latest); }; // 排序 reviews.sort(reviewComparator); // 打印结果 reviews.forEach(System.out::println); } // 工具方法:获取一个Review的最晚日期 private static LocalDateTime getLatestDate(Review review) { LocalDateTime reviewDate = LocalDateTime.parse(review.date); if (review.update == null) { return reviewDate; } LocalDateTime updateDate = LocalDateTime.parse(review.update.date); // 返回较晚的那个日期 return updateDate.isAfter(reviewDate) ? updateDate : reviewDate; } }
修正后输出
运行上述代码,输出会和期望结果完全一致。
说明
- 避免手动操作列表元素的错误逻辑,用标准
Comparator实现排序,代码简洁易维护 - 将日期字符串转为
LocalDateTime对象比较,避免字符串比较可能出现的格式问题 - 提取
getLatestDate工具方法,逻辑清晰,复用性强
内容的提问来源于stack exchange,提问作者Aleksandr Martynets
相关产品推荐
相关产品推荐

