Java使用Stream排序List:将HashSet存在的元素移至列表前端
Java Stream 自定义排序实现Set元素前置
核心逻辑是给元素分优先级:存在于目标HashSet中的元素优先级更高,排序时排在列表前端,同优先级元素保留原始相对顺序即可。
基础实现
直接在sorted()方法中编写比较规则即可,适配你现有的代码框架:
// 替换为你实际的Set和数据源 Set<Object> targetSet = new HashSet<>(); List<Object> sizes = new ArrayList<>(); Set<Object> result = sizes.stream() .sorted((o1, o2) -> { boolean o1Exist = targetSet.contains(o1); boolean o2Exist = targetSet.contains(o2); // 两个元素同属一个分组(都在Set/都不在Set),不调整相对顺序 if (o1Exist == o2Exist) { return 0; } // o1在Set中则排前面,否则o2排前面 return o1Exist ? -1 : 1; }) .collect(Collectors.toCollection(LinkedHashSet::new));
稳定排序优化版
如果需要严格保留同分组内元素在原始列表中的出现顺序,避免排序算法对相等元素的顺序扰动,可以提前记录元素原始索引,二级排序按索引升序排列:
// 记录每个元素第一次出现的原始索引 Map<Object, Integer> originIndex = IntStream.range(0, sizes.size()) .boxed() .collect(Collectors.toMap(sizes::get, Function.identity(), (oldVal, newVal) -> oldVal)); Set<Object> stableResult = sizes.stream() .sorted( // 一级排序:Set内元素优先级为0,外部元素优先级为1,优先级低的排前面 Comparator.comparingInt((Object item) -> targetSet.contains(item) ? 0 : 1) // 二级排序:同优先级按原始索引升序,保留原有顺序 .thenComparingInt(originIndex::get) ) .collect(Collectors.toCollection(LinkedHashSet::new));
注意事项
- 由于
HashSet.contains()的时间复杂度是O(1),上述排序逻辑不会带来明显的性能损耗 - 如果不需要对结果去重,最后收集阶段替换为
Collectors.toList()即可,排序逻辑完全通用 - 收集为
LinkedHashSet可以同时满足去重+保留排序后顺序的需求,和你现有框架的设计一致
内容的提问来源于stack exchange,提问作者andresmonc
相关产品推荐
相关产品推荐

