使用Streams对含嵌套AnswerValues的Answer对象实现复杂排序
解决方案
分两步完成需求,同时规避空指针问题,代码实现如下:
完整代码
// 第一步:遍历每个Answer,将其AnswerValues按id升序排序 laneValues.getAnswers().forEach(answer -> { answer.getAnswerValues().sort(Comparator.comparingInt(AnswerValues::getId)); }); // 第二步:按每个Answer的最小AnswerValues id排序Answer列表,处理空AnswerValues的情况 List<Answer> sortedAnswers = laneValues.getAnswers().stream() .sorted((e1, e2) -> { List<AnswerValues> vals1 = e1.getAnswerValues(); List<AnswerValues> vals2 = e2.getAnswerValues(); // 空AnswerValues的Answer默认排最前面,可根据业务需求调整顺序 if (vals1.isEmpty() && vals2.isEmpty()) { return 0; } if (vals1.isEmpty()) { return -1; } if (vals2.isEmpty()) { return 1; } // 取排序后的第一个元素(即最小id)做比较 return Integer.compare(vals1.get(0).getId(), vals2.get(0).getId()); }) .toList(); laneValues.setAnswers(sortedAnswers);
关键说明
- 先排序单个Answer的AnswerValues:通过
forEach遍历每个Answer,调用List.sort()传入按id升序的比较器,空列表排序后仍为空,不会引发异常。 - 规避空指针问题:在Answer列表的比较器中,先判断两个Answer的AnswerValues是否为空,避免直接调用
get(0)。如果需要把空AnswerValues的Answer排到最后,只需调换return -1和return 1的逻辑。 - 确保取到最小id:因为第一步已经给每个Answer的AnswerValues做了升序排序,所以
get(0)必然是当前Answer中id最小的AnswerValues,直接用它的id比较即可满足需求。
合并版代码(可选)
如果想把两步合并为一个Stream操作,可使用peek先处理单个Answer的排序:
List<Answer> sortedAnswers = laneValues.getAnswers().stream() .peek(answer -> answer.getAnswerValues().sort(Comparator.comparingInt(AnswerValues::getId))) .sorted((e1, e2) -> { List<AnswerValues> vals1 = e1.getAnswerValues(); List<AnswerValues> vals2 = e2.getAnswerValues(); if (vals1.isEmpty() && vals2.isEmpty()) return 0; if (vals1.isEmpty()) return -1; if (vals2.isEmpty()) return 1; return Integer.compare(vals1.get(0).getId(), vals2.get(0).getId()); }) .toList(); laneValues.setAnswers(sortedAnswers);
补充提示
如果AnswerValues.getId()返回的是包装类Integer而非基本类型int,只需把Comparator.comparingInt换成Comparator.comparing,Integer.compare换成vals1.get(0).getId().compareTo(vals2.get(0).getId())即可。
内容的提问来源于stack exchange,提问作者d00d
相关产品推荐
相关产品推荐

