Java Collections排序:比较方法违反了其一般合同

mat*_*law 2 java sorting collections comparison

我知道它已经被问到并且已经回答了数百万次,但我仍然无法弄清楚为什么我在排序期间收到违规行为.这是我的代码:

Collections.sort(sorted, new Comparator<MyObject>() {
    @Override
    public int compare(MyObject m1, MyObject m2) {
        // Actual energy comparison :-
        // THE higher the energy, the earlier in the list
        float delta = m1.getTotalEnergy() - m2.getTotalEnergy();

        if (delta > 0) {
            return 1;
        } else if (delta < 0) {
            return -1;
        } else {
            return 0;
        }
    }
});
Run Code Online (Sandbox Code Playgroud)

我收到这个错误

java.lang.IllegalArgumentException: Comparison method violates its general contract!  
        at java.util.TimSort.mergeHi(TimSort.java:895)  
        at java.util.TimSort.mergeAt(TimSort.java:512)  
        at java.util.TimSort.mergeForceCollapse(TimSort.java:453)  
        at java.util.TimSort.sort(TimSort.java:250)  
        at java.util.Arrays.sort(Arrays.java:1512)  
        at java.util.ArrayList.sort(ArrayList.java:1454)  
        at java.util.Collections.sort(Collections.java:175)
Run Code Online (Sandbox Code Playgroud)

有任何想法吗 ?

Ell*_*sch 6

假设getTotalEnergy()返回float,您可以使用

return new Float(m1.getTotalEnergy()).compareTo(m2.getTotalEnergy());
Run Code Online (Sandbox Code Playgroud)

使用Float.valueOf(float)可能稍微有点效率,希望这更容易阅读.

Float f1 = Float.valueOf(m1.getTotalEnergy());
Float f2 = Float.valueOf(m2.getTotalEnergy());
return f1.compareTo(f2);
Run Code Online (Sandbox Code Playgroud)

  • 首选`返回Float.valueOf(m1.getTotalEnergy()).compareTo(m2.getTotalEnergy());`允许它从缓存中使用`Float`而不是总是创建一个新的. (2认同)