(原)
今天看了一下现场的环境,发现有个其它部门的项目用到了这样一个参数:html
-Djava.util.Arrays.useLegacyMergeSort=true
因而查看了一下什么做用。java
在JDK1.6和JDK1.7的版本中,使用comparator排序可能在1.6版本中正常运行,而在1.7版本有时会报异常,IllegalArgumentException(异常的内容大概是:Comparison method violates its general contract!)。python
在JDK7的不兼容列表中,能够看到这样一条消息:算法
Area: API: Utilities Synopsis: Updated sort behavior for Arrays and Collections may throw an IllegalArgumentException Description: The sorting algorithm used by java.util.Arrays.sort and (indirectly) by java.util.Collections.sort has been replaced. The new sort implementation may throw an IllegalArgumentException if it detects a Comparable that violates the Comparable contract. The previous implementation silently ignored such a situation. If the previous behavior is desired, you can use the new system property, java.util.Arrays.useLegacyMergeSort, to restore previous mergesort behavior. Nature of Incompatibility: behavioral RFE: 6804124
大概意思就是 Arrays.sort方法和Collections.sort(底层也是Arrays.sort)方法被替换了,若是违反了新的排序规则就可能会出现IllegalArgumentException异常(这里是可能,不是必定)。以前的方法会忽略掉一种状况,若是想使用以前的方法,这里提供了一个新的参数,java.util.Arrays.useLegacyMergeSort去还原以前的方法。api
再来看看Arrays.sort的实现bash
它是有二种排序方法,legacyMergeSort和TimSort。oracle
旧的排序方式为legacyMergeSort,新的为TimSort,若是要用旧的排序方式,能够在系统属性中加上 java.util.Arrays.useLegacyMergeSort=true 这个参数。svn
再看看Collections.sort方法的说明:函数
大概意思新的TimSort排序方法的实现须要知足三种状况:spa
- sgn(compare(x, y)) == -sgn(compare(y, x))
- ((compare(x, y)>0) && (compare(y, z)>0)) implies compare(x, z)>0
- compare(x, y)==0 implies that sgn(compare(x, z))==sgn(compare(y, z)) for all z
对于函数sgn(compare(x,y)),因为compare(x,y)的返回结果有0、一、-1三种,sgn(x)的结果也有三种,
一、当compare(x,y) < 0 时,sgn(compare(x,y))结果为-1
二、当compare(x,y) = 0 时,sgn(compare(x,y))结果为0
三、当compare(x,y) > 0 时,sgn(compare(x,y))结果为1
最容易出错的状况就是本身写的比较器只写了1和-1的状况,而没有写0,如:
return x > y ? 1 : -1;
这样会导至当x == y时,compare(x,y)的结果为 -1,此时sgn(compare(x,y)) = -1,这与第一种知足条件sgn(compare(x, y)) == -sgn(compare(y, x))相违背。因此会抛出IllegalArgumentException异常。
对于 x > y ? 1 : -1 ,当x == y时,也只是可可能会抛出异常,什么会抛出该异常,这要取绝于TimSort算法。