整数排序中的坑

Java中对集合或者数组排序一般有两个方法,类实现Comparable 接口或者 排序时使用定制化接口 Comparator。
以TreeSet为例,日常写法:

1
2
3
4
5
6
7
8
9
10
11
 Set<Integer> sets = new TreeSet<>(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2 == o1 ? 0 : o2 > o1 ? 1 : -1;
}
});
sets.add(1);
sets.add(-1);
sets.add(100);
System.out.println(Arrays.toString(sets.toArray(new Integer[]{})));
//[100, 1, -1]

关于上面的写法,还有一种变种,就是改成o2-o1,似乎没有问题,看源码,使用Comparator的时候,是按照正负进行判断的

坑来了

看例子

1
2
3
4
5
6
7
8
9
10
11
Set<Integer> sets = new TreeSet<>(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2-o1;
}
});
sets.add(1);
sets.add(-1);
sets.add(Integer.MIN_VALUE);
System.out.println(Arrays.toString(sets.toArray(new Integer[]{})));
[-2147483648, 1, -1]

是不是不是预想的结果了,-2147483648成了最大值。

原因:

很简单,做个测试 -2147483648 -1 = ? 答案是 2147483648。
数字在边界处会溢出,比如 2147483648+1=-2147483648

最佳实践:

使用Comparator接口工作时,一定使用比较将结果控制在-1 ,0 1 三个值,保证结果稳定,如果使用数字加减排序,有可能因为有数字溢出导致结果异常。