【问题标题】:Collection Sort [duplicate]集合排序[重复]
【发布时间】:2017-05-11 07:05:57
【问题描述】:

我有这个代码,用于排序值的比较器:

public static Comparator<Partikel> getFFsorted() {
    Comparator comp = new Comparator<Partikel>() {
        @Override
        public int compare(Partikel s1, Partikel s2) {
            if(s1.ff>s2.ff)
            {
                return 1;
            }
            else
            {
                return -1;
            }
        }
    };
    return comp;
}

但我有这样的错误:

线程“主”java.lang.IllegalArgumentException 中的异常: 比较方法违反了它的总合同!在 java.util.TimSort.mergeHi(TimSort.java:868)

在 java.util.TimSort.mergeAt(TimSort.java:485)

在 java.util.TimSort.mergeCollapse(TimSort.java:410)

在 java.util.TimSort.sort(TimSort.java:214)

在 java.util.TimSort.sort(TimSort.java:173)

在 java.util.Arrays.sort(Arrays.java:659)

在 java.util.Collections.sort(Collections.java:217)

我该如何解决?

【问题讨论】:

  • “比较方法违反了它的一般约定!”当你read what that contract is,并将它与你的代码进行比较时,你什么都没有发现?

标签: java sorting collections


【解决方案1】:

您的方法无法处理等于 ff 的情况。

因此,compare(s1,s2)compare(s2,s1)s1.ff == s2.ff 时都将返回 -1。这违反了compare 的合同,要求sgn(compare(x, y)) == -sgn(compare(y, x)) for all x and y

    public int compare(Partikel s1, Partikel s2) {
        if(s1.ff > s2.ff) {
            return 1;
        } else if (s1.ff < s2.ff) {
            return -1;
        } else {
            return 0;
        }
    }

【讨论】:

    【解决方案2】:

    Partikel 类中的那些 ff 成员对我来说看起来像是数字......

    所以最好从包装类中实现静态方法..

    类似:

    @Override
    public int compare(Partikel p1.ff, Partikel p2) {
        return Integer.compare(p1.ff, p2.ff);
        //or
        return Double.compare(p1.ff, p2.ff);
        //or
        return Long.compare(p1.ff, p2.ff);
        //or
        return Float.compare(p1.ff, p2.ff);
    }
    

    【讨论】:

      【解决方案3】:

      你不处理值相等的情况。

      Java 具有内置函数,可以为您可以使用的每种原始数据类型(Integer、Long、Float、Double 等)正确比较包装类中的原始数据类型:

      Comparator comp = new Comparator<Partikel>() {
          @Override
          public int compare(Partikel s1, Partikel s2) {
              return Integer.compare(s1.ff, f2.ff);
              // Or Long.compare, Float.compare, Double.compare, etc.
              // depending on the datatype of the field "ff".
          }
      };
      

      【讨论】:

        【解决方案4】:

        如果比较器中有任何 NaN 值,就会发生这种情况

        例如:

        public class Demo
        {
            public static void main(String[] args) {
                double a = Double.NaN;
                double b = Double.NaN;
        
                System.out.println(a < b);
                System.out.println(a > b);
        

        } }

        所有这些都打印错误。因此,您最终可能会遇到两个非 NaN 值都被视为“等于”NaN,但一个大于另一个的情况。基本上,您应该弄清楚要如何处理 NaN 值。当然,还要检查这确实是问题所在……您真的想要 Partikel 的 NaN 值吗?

        And also the default comparator has implementation to compare for three cases i.e
             1.Greater than
             2. Less than 
             3. Equal to 
        

        因为你只拿了两个,所以尝试分成三个如下:

         public int compare(Partikel s1, Partikel s2) {
            if(s1.ff>s2.ff)
                return 1;
            else if(s1.ff<s2.ff)
                return -1;
         //for equality  
          else
                return 0;
        }
        

        【讨论】:

        • 没有Integer.NaN 这样的东西——只有Float.NaNDouble.NaN
        猜你喜欢
        • 2012-08-21
        • 1970-01-01
        • 2013-01-31
        • 2019-07-05
        • 2010-11-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多