Java Collections sort:比较方法违反了它的一般合同 [英] Java Collections sort: Comparison method violates its general contract

查看:728
本文介绍了Java Collections sort:比较方法违反了它的一般合同的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I know it has been asked and answered millions of times but still I am unable to figure out why I am receiving with the violation during sort. Here is my code:

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;
        }
    }
});

我收到此错误

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)

有什么想法吗?

推荐答案

以下代码已使用float,NaN和null值测试。所有情况都正确处理。我创建了一个 hashCode() equals()方法到 MyObject class。

The following code has been tested with float, NaN, and null values. All cases are handled correctly. I created a hashCode() and equals() method to the MyObject class.

结果: [null,0.0,1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0 ,NaN]

package q28004269;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class SortObjectFloatProperty {
    public static void main(String[] args) {
        List<MyObject> sorted;

        sorted = create(1f, 4f, 6f, null, 8f, 5f, Float.NaN, 3f, 2f, 7f, 0f, 9f);

        Collections.sort(sorted, new Comparator<MyObject>() {
            @Override
            public int compare(MyObject m1, MyObject m2) {
                if (m1 == m2) return 0;
                if (m1 == null) return -1;
                if (m2 == null) return 1;
                if (m1.equals(m2)) return 0;
                int value = Float.compare(m1.getTotalEnergy(), m2.getTotalEnergy());
                if (value != 0) return value;
                return m1.hashCode() - m2.hashCode();
            }
        });

        System.out.println(sorted);
    }

    public static MyObject create(float totalEnergy) {
        return new MyObject(totalEnergy);
    }

    public static List<MyObject> create(Object ...values) {
        List<MyObject> objs = new ArrayList<SortObjectFloatProperty.MyObject>();
        for (int i = 0; i < values.length; i++) {
            if (values[i] instanceof Float) {
                objs.add(create((float) values[i]));
            } else {
                objs.add(null);
            }
        }
        return objs;
    }
}



MyObject



MyObject

package q28004269;

public static class MyObject {
    private float totalEnergy;

    public float getTotalEnergy() {
        return totalEnergy;
    }

    public void setTotalEnergy(float totalEnergy) {
        this.totalEnergy = totalEnergy;
    }

    public MyObject() {
        this(0.0f);
    }

    public MyObject(float totalEnergy) {
        this.totalEnergy = totalEnergy;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + Float.floatToIntBits(totalEnergy);
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null) return false;
        if (getClass() != obj.getClass()) return false;
        MyObject other = (MyObject) obj;
        return !(Float.floatToIntBits(totalEnergy) != Float.floatToIntBits(other.totalEnergy));
    }

    @Override
    public String toString() {
        return Float.toString(totalEnergy);
    }
}

这篇关于Java Collections sort:比较方法违反了它的一般合同的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆