1

I have following classes-

public class Pair
{
    public double value;
    int id;

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

PairComparator class to be used for implementing Comparator class

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

I'm trying to sort a Pair collection as follows-

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

However I'm getting following error-

`Exception in thread "main" java.lang.IllegalArgumentException: Comparison method violates its general contract!

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)
7
  • @MadushanPerera I don't exactly have the list items as inserted in the above code, do you think that the code might be producing error due to problem in the data? Commented Nov 23, 2015 at 5:52
  • No if you did not provide the list items it should compile and run fine but without any out-put. Commented Nov 23, 2015 at 5:56
  • I mean I have data in the list but it is not inserted in the way as done in the above list, so is it possible that the comparator class gives this particular error because of the incompatibility of datatype? Commented Nov 23, 2015 at 5:59
  • Incompatibility of datatype right away gives you a compile error since you cant pass String value as the first parameter of your Pair class constructor . Commented Nov 23, 2015 at 6:15
  • "is not inserted in the way as done in the above list" so which way you have inserted ??? Commented Nov 23, 2015 at 6:16

3 Answers 3

5

You usually get this error when the comparator violates the transitivity - check this answer.

When using double in a Comparator, you should avoid using the substraction logic. Since you're converting the result into an int, it would be rounded and thus would break transitivity while comparing values like 5.1, 5.2 etc. Check this answer for details.

You're better off using a comparator logic as so:

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

As mentioned by sarilks - if you're expecting NaN values better use in-built compare function -

public int compare(Pair p1, Pair p2){
    return Double.compare(p1.value, p2.value);
}
Sign up to request clarification or add additional context in comments.

Comments

4

Since you are comparing Double values , its safer to use Double.compare

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

Comments

4

In Java-8 you can do this safely and without additional PairComparator class:

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.