无法比较用户定义的对象进行排序(Java 8)

时间:2015-11-23 05:40:00

标签: java sorting collections

我有以下课程 -

public class Pair
{
    public double value;
    int id;

    Pair(){
        value=0;
        id=0;
    }
    Pair(double value, int id){
        this.value=value;
        this.id=id;
    }
}

用于实现Comparator类

的PairComparator类
public class PairComparator implements Comparator<Pair>{
    @Override
    public int compare(Pair p1, Pair p2){
        return (int)(p2.value-p1.value);
    }
}

我尝试按如下方式对Pair集合进行排序 -

List<Pair> list= new ArrayList<Pair>();
list.add(new Pair(5.2, 4));
list.add(new Pair(3.4, 5));
list.add(new Pair(10.3, 3));

Collections.sort(list, new PairComparator());

但是我收到了以下错误 -

`线程中的异常&#34; main&#34; java.lang.IllegalArgumentException:比较方法违反了它的一般合同!

Exception in thread "main" 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.mergeCollapse(TimSort.java:435)
at java.util.TimSort.sort(TimSort.java:241)
at java.util.Arrays.sort(Arrays.java:1512)
at java.util.ArrayList.sort(ArrayList.java:1454)
at java.util.Collections.sort(Collections.java:175)
at com.research.priyanshuid.recommendation_system.MatrixRecalculation.main(MatrixRecalculation.java:59)

3 个答案:

答案 0 :(得分:5)

当比较器违反传递性时,通常会出现此错误 - check this answer

在比较器中使用double时,应避免使用减法逻辑。由于您将结果转换为int,因此它会被舍入,因此会在比较5.1,5.2等Check this answer之类的值时打破传递性。

最好使用比较器逻辑:

public int compare(Pair p1, Pair p2) {
   if (p1.value < p2.value) return -1;
   if (p1.value > p2.value) return 1;
   return 0;
}

如sarilks所述 - 如果您期望NaN值更好地使用内置比较功能 -

public int compare(Pair p1, Pair p2){
    return Double.compare(p1.value, p2.value);
}

答案 1 :(得分:4)

由于您要比较Double值,因此使用i

更安全
Double.compare

答案 2 :(得分:4)

在Java-8中,您可以安全地执行此操作,无需额外的PairComparator类:

Collections.sort(list, Comparator.comparingDouble(p -> p.value));