基于Reactor Flux分组排序列表:将Not Applicable置于每组底部
Reactor Flux分组后自定义排序实现
针对你用Reactor Flux处理容器列表的需求,这里给出完整的实现方案,核心是在分组后对每个组内的ContainerTypeDto应用自定义排序规则:将名称为"Not Applicable"的项置于底部,其余数字开头的项按规则排序。
核心排序规则实现
首先定义自定义Comparator,实现你的排序逻辑:
Comparator<ContainerTypeDto> containerSortComparator = (dto1, dto2) -> { boolean isDto1NA = "Not Applicable".equals(dto1.getName()); boolean isDto2NA = "Not Applicable".equals(dto2.getName()); // 处理"Not Applicable"项的优先级 if (isDto1NA && isDto2NA) { return 0; } else if (isDto1NA) { return 1; // 当前项是NA,排到后面 } else if (isDto2NA) { return -1; // 对比项是NA,当前项排前面 } // 数字开头项的精准排序:先按开头数字排序,再按剩余文本排序 Integer num1 = extractLeadingNumber(dto1.getName()); Integer num2 = extractLeadingNumber(dto2.getName()); int numCompare = num1.compareTo(num2); if (numCompare != 0) { return numCompare; } // 数字相同则比较后续文本 return dto1.getName().substring(num1.toString().length()).trim() .compareToIgnoreCase(dto2.getName().substring(num2.toString().length()).trim()); }; // 辅助方法:提取名称开头的数字 private Integer extractLeadingNumber(String name) { Pattern pattern = Pattern.compile("^\\d+"); Matcher matcher = pattern.matcher(name); return matcher.find() ? Integer.parseInt(matcher.group()) : Integer.MAX_VALUE; }
完整Flux处理流程
将排序逻辑嵌入你的现有处理链中:
// 原始容器Flux Flux<Container> containers = ...; Flux<ContainerDto> finalResult = containers // 转换为ContainerTypeDto .map(this::convertToContainerTypeDto) // 按category分组 .groupBy(ContainerTypeDto::getCategory) // 处理每个分组:排序→收集→转换为ContainerDto .flatMap(group -> group .sort(containerSortComparator) .collectList() .map(sortedDtos -> buildContainerDto(group.key(), sortedDtos)) );
代码说明
- NA项置底:优先判断名称是否为"Not Applicable",直接将这类项的排序权重设为最低,确保它们出现在分组末尾;
- 数字精准排序:通过
extractLeadingNumber提取名称开头的数字,先按数字大小排序,数字相同再对比后续文本,比单纯的自然排序更贴合你的需求; - 分组后处理:
groupBy后对每个分组的Flux执行sort,再收集为有序列表,最后转换为目标ContainerDto。
如果不需要精准的数字排序,仅需自然排序,可将Comparator的数字处理部分替换为:
return dto1.getName().compareToIgnoreCase(dto2.getName());
内容的提问来源于stack exchange,提问作者shreya khattar
相关产品推荐
相关产品推荐

