Java 13下Collections.sort排序异常:特定输入最小值未正确排序
排序异常问题分析与修复
这段代码在多数场景下运行正常,但处理包含极值整数的数组时会出现排序错误——比如给定的输入数组中,最小值-1795085364始终被排在数组末尾。
问题根源
排序逻辑中使用a[0] - b[0]作为Comparator的返回值,会触发int类型溢出:
Java的int是32位有符号整数,取值范围是-2^31到2^31-1(即-2147483648到2147483647)。当两个int值的差超出这个范围时,会发生溢出,导致计算结果的符号反转,完全打乱Comparator的排序逻辑。
以输入里的最小值-1795085364和大数2145575295为例:-1795085364 - 2145575295 = -3940660659,这个结果远小于int的最小值,溢出后会变成正数2354306637。此时Comparator会错误地认为-1795085364比2145575295大,因此排序时将最小值放到了数组末尾。
修复方案
以下三种方法均可安全解决溢出问题,推荐使用前两种更简洁的方式:
使用Integer.compare()方法
该方法内部已经处理了溢出情况,是最直接的修复方式:Collections.sort(numsIndexed, (a, b) -> Integer.compare(a[0], b[0]));使用Comparator.comparingInt()方法
Java 8及以上版本支持的更简洁写法,可读性更强:Collections.sort(numsIndexed, Comparator.comparingInt(arr -> arr[0]));手动判断大小(避免减法)
通过直接比较数值大小返回结果,从根源上避免溢出风险:Collections.sort(numsIndexed, (a, b) -> { if (a[0] < b[0]) { return -1; } else if (a[0] > b[0]) { return 1; } else { return 0; } });
内容的提问来源于stack exchange,提问作者RichardFeynman
相关产品推荐
相关产品推荐

