如何用Java Stream按Channel分组并对RRF取最小order的标题?
问题描述
现有如下PdfTitleCustomizationDto集合:
List<PdfTitleCustomizationDto> dtoList = Arrays.asList( new PdfTitleCustomizationDto("Title 1", 1, "RRF", Set.of(new Role("ADMIN"))), new PdfTitleCustomizationDto("Title 2", 2, "Other", Set.of(new Role("USER"))), new PdfTitleCustomizationDto("Title 3", 3, "RRF", Set.of(new Role("ADMIN"))), new PdfTitleCustomizationDto("Title 4", 4, "Other", Set.of(new Role("ADMIN"))) );
需求:按channel(取值为RRF或Other)进行分组,其中当channel为RRF时,仅保留order最小的单个标题;Other保留所有标题并按order降序排列。预期结果如下:
{RRF=[Title 1], Other=[Title 4, Title 2]}
请问如何通过一次Stream操作实现该需求?
实现方案
可以通过Collectors.groupingBy结合Collectors.collectingAndThen完成一次Stream分组并处理逻辑,代码如下:
Map<String, List<String>> result = dtoList.stream() .collect(Collectors.groupingBy( PdfTitleCustomizationDto::getChannel, Collectors.collectingAndThen( Collectors.toList(), groupList -> { String channel = groupList.get(0).getChannel(); if ("RRF".equals(channel)) { // 筛选RRF分组中order最小的元素,转为单元素标题列表 return groupList.stream() .min(Comparator.comparingInt(PdfTitleCustomizationDto::getOrder)) .map(dto -> Collections.singletonList(dto.getTitle())) .orElse(Collections.emptyList()); } else { // Other分组按order降序排序,提取标题列表 return groupList.stream() .sorted(Comparator.comparingInt(PdfTitleCustomizationDto::getOrder).reversed()) .map(PdfTitleCustomizationDto::getTitle) .collect(Collectors.toList()); } } ) ));
代码说明
- 分组基础:通过
Collectors.groupingBy(PdfTitleCustomizationDto::getChannel)按频道分组,将相同channel的Dto归为一组。 - 分组后处理:使用
Collectors.collectingAndThen对每个分组的列表做二次处理:- 对于
RRF分组:利用min()方法结合order的比较器,找到order最小的Dto,再包装成单元素的标题列表。 - 对于
Other分组:先按order倒序排序,再提取每个Dto的标题,最终收集为列表,匹配预期的顺序。
- 对于
内容的提问来源于stack exchange,提问作者yaroslav96
相关产品推荐
相关产品推荐

