【问题标题】:Cannot compare user-defined objects for sorting (Java 8)无法比较用户定义的对象进行排序(Java 8)
【发布时间】:2015-11-23 15:13:19
【问题描述】:

我有以下课程-

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

但是我遇到了以下错误-

`线程“main”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)

【问题讨论】:

  • @MadushanPerera 我没有完全插入上面代码中的列表项,您是否认为代码可能由于数据问题而产生错误?
  • 否,如果你没有提供它应该编译和运行良好但没有任何输出的列表项。
  • 我的意思是我的列表中有数据,但它没有按照上面列表中的方式插入,那么比较器类是否可能由于数据类型的不兼容而出现此特定错误?
  • 数据类型不兼容会立即给您一个编译错误,因为您不能将字符串值作为Pair 类构造函数的第一个参数传递。
  • “没有按照上面列表中的方式插入”所以你是用哪​​种方式插入的???

标签: java sorting collections


【解决方案1】:

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

在比较器中使用双精度时,应避免使用减法逻辑。由于您将结果转换为 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);
}

【讨论】:

    【解决方案2】:

    由于您正在比较 Double 值,因此使用 Double.compare 更安全

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

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

        猜你喜欢
        • 2016-02-02
        • 1970-01-01
        • 2013-05-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多