我有一个对象集合:
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")))
);
我需要按频道对其进行分组,即“RRF”或“其他”。但是,如果频道是“RRF”,我只能获得一个最小订单的标题。 所以预期的结果应该是:
{RRF=[Title 1], Other=[Title 4, Title 2]}
您有什么想法如何在一个流中做到这一点吗?
您可以
groupBy
,并在下游使用 teeing
将流分成 2 部分 - 一个执行 minBy
,另一个执行 toList
。在合并参数中,您将检查标题并决定是否使用列表或最小元素。
var y = list.stream().collect(
Collectors.groupingBy(
PdfTitleCustomizationDto::getChannel,
Collectors.teeing(
Collectors.minBy(Comparator.comparing(PdfTitleCustomizationDto::getTitle)),
Collectors.toList(),
(min, list) -> min
.filter(x -> "RRF".equals(x.getTitle()))
.map(List::of)
.orElse(list)
)
)
);
这确实意味着所有内容,包括那些没有“RRF”标题的内容,都将被
minBy
'ed,这是您不需要进行的一些额外处理。
如果这是一个问题,我建议只
groupBy
,并从结果映射中删除非最小元素,或者根本不使用流。
我相信你可以使用 Collector 得到你需要的东西
看看下面的代码。
Map<String,List<PdfTitleCustomizationDto>> result = dtoList.stream()
.collect(Collectors.groupingBy(
PdfTitleCustomizationDto::getChannel,
Collectors.collectingAndThen(
Collectors.minBy(Comparator.comparingInt(PdfTitleCustomizationDto::getOrder)),
optionalDto - > optionalDto.map(Collections::singletonList).orElse(Collections.emptyList())
)
));