错误:比较方法违反了其一般合同

时间:2017-04-30 23:11:53

标签: java android comparator

我知道有很多与此主题相关的问题,但我无法完全理解导致此错误的原因

 Collections.sort(noteList,new Comparator<ClassNote>(){
        @Override
        public int compare(ClassNote b, ClassNote a) {
           DateFormat formatter = new SimpleDateFormat("MMMM dd HH:mm", Locale.US);
           try {
               Date date2 = formatter.parse(b.getCallDate());
               Date date1 = formatter.parse(a.getCallDate());
               if ( date1 == null ) {
                   if ( date2 == null) {
                       return 0;
                   }
                   return 1;
               }
               if ( date2 == null ) {
                   return -1;
               }
               return date2.compareTo(date1);
           } catch (ParseException e) {
               e.printStackTrace();
               return 1;
           }
        }
    });

有谁知道为什么它不起作用以及如何解决它?

2 个答案:

答案 0 :(得分:0)

如果比较ClassNoteab的两个实例,解析其中一个实例会抛出异常:

compare(a, b)将返回a更大。

compare(b, a)将返回b更大。

比较返回值不一致。

答案 1 :(得分:0)

我认为在这种情况下最好的计划是,而不是专注于&#34;如何让我的比较功能保持一致&#34;,请改为#34;我想要一个排序的数组看起来像& #34 ;?当您处理特殊情况时,这一点尤其重要。一旦找出正确的顺序,就编写一个比较函数,为您提供该订单。

在这里,您有三个ClassNote类别正在处理:

  1. ClassNote具有有效日期的对象
  2. 解析日期的
  3. ClassNote个对象返回null
  4. 解析日期的
  5. ClassNote个对象抛出异常
  6. 类别1很简单:您希望按日期排序对象。 (你还必须弄清楚当两个ClassNote具有相同日期时会发生什么,但在这种情况下,你可能不关心订单,这很好。在某些情况下,你可能需要物品同一日期要按其他字段排序。)

    对于#2和#3,你在结果中想要它们在哪里?到目前为止,看起来您首先需要null个,但您还没有处理解析异常。我可以看到两种简单的方法:

    1. null视为异常。然后所有的空值和异常情况都会以某种顺序出现并且会混合在一起,但这可能没问题。
    2. 将它们分组,使#2项先到,然后是#3,然后是有效日期的项目。或者另一种方式:#3,然后是#2,然后是有效日期。
    3. 任何一种方法都可以,但你必须决定你想要什么。

      假设你采用方法#1。现在你必须安排一些事情,这样当你将#2项目与#3项目进行比较时,结果为0;当你将#2或#3项与#1进行比较时,#2或#3总是更少。您可以修改现有代码

       Date date2 = formatter.parse(b.getCallDate());
       Date date1 = formatter.parse(a.getCallDate());
      

      到此:

       Date date2 = parseOrReturnNull(b.getCallDate());
       Date date1 = parseOrReturnNull(a.getCallDate());
      

      其中parseOrReturnNull是使用formatter.parse()的帮助方法,捕获ParseException,如果有异常,则返回 null 。现在,您的其余逻辑将确保将null和解析异常用于排序目的。

      如果您想分别对null和例外进行分组,一种解决方案是添加&#34;类别&#34;您应用于每个ClassNote的变量。该类别将以正确的顺序指示ClassNote所属的类别:因此,如果您首先需要null,那么例外,然后是有效日期,您可以为{{1 1,例外,2表示有效日期。 (更好的是,使用null)。然后,对于每个日期,您都要计算类别和enum。事实上,最好宣布一个新类:

      date

      使用一个class ComparisonDate { int category; // or enum Date date; // meaningful only if the date is valid } 的辅助方法并返回ClassNote。然后,您可以将两个ComparisonDate s与以下代码进行比较:

      ComparisonDate

      我可能已切换if (cd1.category != cd2.category) { return Integer.compare(cd1.category, cd2.category); } else if (cd1.category == 2) { // 2 means they have valid dates return cd1.date.compareTo(cd2.date); } else { // ComparisonDates are in same category and dates aren't // meaningful return 0; // so treat them as equal } cd1,但您可以解决这个问题。