-2

I have this code, comparator for sorting values:

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

but I have an error like this :

Exception in thread "main" java.lang.IllegalArgumentException: Comparison method violates its general contract! at java.util.TimSort.mergeHi(TimSort.java:868)

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

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

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

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

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

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

How do I fix it?

Draken
  • 3,134
  • 13
  • 34
  • 54
  • 1
    *"Comparison method violates its general contract!"* And when you [read what that contract is](http://docs.oracle.com/javase/8/docs/api/java/util/Comparator.html#compare-T-T-), and compared it with your code, nothing jumped out at you? – T.J. Crowder May 11 '17 at 07:12

4 Answers4

1

Your method doesn't handle the case of equal ff.

As a result compare(s1,s2) and compare(s2,s1) will both return -1 when s1.ff == s2.ff. This violates the contract of compare, which requires that 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;
        }
    }
Eran
  • 387,369
  • 54
  • 702
  • 768
0

those ff members in the Partikel class look like something numeric to me...

so it would be better that you implement the static method from the wrapper class..

something like:

@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);
}
ΦXocę 웃 Пepeúpa ツ
  • 47,427
  • 17
  • 69
  • 97
0

This will happen if you have any NaN values in your comparator

For example:

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

} }

All of these print false. So you could end up in a situation where two non-NaN values were both deemed "equal" to NaN, but one was greater than the other. Basically, you should work out how you want to handle NaN values. Also check that that really is the problem, of course... do you really want NaN values for your Partikel?

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

Since you are taking only two ,so try to segregate into three as follows :

 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;
}
Vishesh
  • 308
  • 1
  • 9
0

You don't handle the case where the values are equal.

Java has builtin functions to correctly compare primitive data types in the wrapper class for each primitive data type (Integer, Long, Float, Double, etc) which you can use:

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".
    }
};
Erwin Bolwidt
  • 30,799
  • 15
  • 56
  • 79