
本文详解如何使用 Java 对整数列表实现「先按元素出现频率降序,频率相同时按元素值升序」的稳定排序,重点解决 Collections.sort() 类型不匹配错误,并提供现代 Stream + Comparator 链式写法。
本文详解如何使用 java 对整数列表实现「先按元素出现频率降序,频率相同时按元素值升序」的稳定排序,重点解决 `collections.sort()` 类型不匹配错误,并提供现代 stream + comparator 链式写法。
在实际开发中,我们常需对数据进行多级排序——例如统计词频后,高频词优先展示,同频时按字典序或数值大小排列。本例要求:给定整数列表 [42, 5, 17, 42, 42, 17, 5, 42],先按各数字出现频次从高到低排序,频次相同时按数字本身从小到大排序,最终输出为 [42, 42, 42, 42, 5, 5, 17, 17]。
原始代码报错的根本原因在于类型不匹配:Collections.sort(List
✅ 正确思路是:不排序 Map 的 Entry,而是排序原始 List 的 Integer 元素,但在比较逻辑中动态查表获取频次。推荐使用 Java 8+ 的函数式风格,简洁且类型安全:
import java.util.*;
import java.util.stream.Collectors;
import java.util.function.Function;
public static void sortByFreq(List<integer> items) {
// 步骤1:构建频次映射(使用 Long 避免 int 溢出风险,且 Collectors.counting() 返回 Long)
Map<integer long> counter = items.stream()
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
// 步骤2:对原始列表就地排序
// 主排序键:频次(降序)→ 使用 .reversed()
// 次排序键:数值本身(升序)→ 使用 Function.identity()
items.sort(
Comparator.comparing((Integer i) -> counter.get(i))
.reversed()
.thenComparing(Function.identity())
);
}</integer></integer>
? 关键说明与注意事项:
- counter.get(i) 返回 Long,Comparator.comparing 可自动推导泛型,无需显式类型转换;
- .reversed() 作用于频次比较器,实现高频在前;.thenComparing(Function.identity()) 实现同频时小数在前;
- 使用 items.sort(...)(List 接口方法)而非 Collections.sort(...),避免静态方法类型推导歧义;
- 若需保持原列表不变,可先创建副本:List
sorted = new ArrayList(items); sorted.sort(...);; - 频次统计推荐 Collectors.counting()(返回 Long)而非手动 getOrDefault(..., 0) + 1,更简洁且线程安全(流式操作天然无竞态)。
? 进阶提示:若需扩展为「频次升序 + 数值降序」,只需调整为 .thenComparing(Function.identity()).reversed()(注意 reversed() 作用于整个链),或分别调用 .reversed() 和 .reversed() 实现精准控制。
该方案兼具可读性、健壮性与现代 Java 最佳实践,彻底规避了原始代码中的类型错误,是处理多级自定义排序的推荐范式。










