How to Fix Comparison Method Violates Its General Contract Error in Java
- 
          
            Difference Between ComparatorandComparableInterfaces
- 
          
            Comparison Rules for ComparatorandComparable
- 
          
            Java Code Having the comparison method violates its general contractError
- 
          
            Java Solutions Using the ComparatorandComparableInterfaces
 
Today, we will learn about the comparison rules used by the Comparator and Comparable interfaces, which will lead to possible causes of the comparison method violates its general contract error in Java. After that, we will understand two solutions using Comparator and Comparable interfaces.
Difference Between Comparator and Comparable Interfaces
    
These are two interfaces in Java core libraries. The Comparator is a function that compares two different objects and is independent of anything else.
It only looks for its two inputs, continues its process with them, and presents the results.
On the other hand, the Comparable is an interface that we mix with a data class. For instance, we have a class with some data; the Comparable interface will be used to compare this class’s first object with the same class’s second object.
It means the Comparable interface indicates that this instance can be compared with another instance of the same class. Remember, the Comparable defines the natural order for the class.
In other respects, it is also a comparison function just like the Comparator and has the same rules for the return value, transitive, reflexive, etc.
Comparison Rules for Comparator and Comparable
The comparison method violates its general contract means that the Comparator or Comparable (based on what we are using) has a bug and violates one of the consistency rules. What are the consistency rules?
Let’s learn them below.
We assume that we have written our Java program for integer-type values. So, our comparison function must adhere to the following rules.
- 
Given any two integers aandb, the Trichotomy Law must be satisfied, which means exactly one of the following relations must be true:- ais less than- b(it returns- -vevalue if- a < b)
- aequals- b(it returns- 0if- a == b)
- ais greater than- b(it returns- +vevalue if- a > b)
 
- 
It must satisfy the Transitivity, which means if a < bandb < cthen, for any three numbersa,b,c, it impliesa < c.
- 
The third rule is about Antisymmetry, where a < bimplies~b < a
- 
Substitutability is also a comparison rule that says, suppose, a == banda < c; this impliesb < c.
- 
The final comparison rule is Reflexivity, where a == a; also~a < a.
If any of these rules are violated, we get the error saying the comparison method violates its general contract. Let’s learn it with the help of a code example below.
Java Code Having the comparison method violates its general contract Error
Example Code:
// import libraries
import static java.util.stream.Collectors.toCollection;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Random;
// Main
public class Main {
  public static void main(String[] args) {
    // generate random numbers
    List<Integer> list = new Random(209).ints(32L).boxed().collect(toCollection(ArrayList::new));
    // sort using lambda expression
    list.sort(logging((a, b) -> a - b));
  } // end main()
  // logging the comparisons
  static Comparator<Integer> logging(Comparator<Integer> c) {
    return (a, b) -> {
      int r = c.compare(a, b);
      System.err.printf("%,14d %,14d => %,14d\n", a, b, r);
      return r;
    };
  } // end logging()
} // end class
In this code, we are generating a few random numbers by using the ints instance of the Random class, which is used to generate the stream of random numbers.
For this code, if we sort as list.sort((a, b) -> a - b); then, we will not be able to identify what the problem is and where it is happening. That’s why we are sorting it via logging, which will help us to identify it.
It gives us an error, but it also provides a lot of comparisons of numbers. We will not discuss all, but a few of them are enough to find the error.
OUTPUT:

As we can see, the program violates the consistency rule here, resulting in this error. In the next section, let’s have the solution using Comparator and Comparable.
Java Solutions Using the Comparator and Comparable Interfaces
Let’s use the Comparator interface with fewer random numbers.
Example Code:
// import libraries
import static java.util.stream.Collectors.toCollection;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Random;
// Main
public class Main {
  public static void main(String[] args) {
    // generate random numbers
    List<Integer> list = new Random(5).ints(32L).boxed().collect(toCollection(ArrayList::new));
    // sort using lambda expression
    list.sort(logging((a, b) -> a - b));
  } // end main()
  // logging the comparisons
  static Comparator<Integer> logging(Comparator<Integer> c) {
    return (a, b) -> {
      int r = c.compare(a, b);
      System.err.printf("%,14d %,14d => %,14d\n", a, b, r);
      return r;
    };
  } // end logging()
} // end class
This code is executed successfully. We are not going through all the comparisons, but we will see a few of them to confirm.
Check the following screenshot.
OUTPUT:

Let’s learn about the error-free Java code using the Comparable interface for making comparisons. To use this interface, we have to make a class containing data.
Let’s do it below.
Example Code (Students.java class):
public class Student implements Comparable<Student> {
  private String firstName;
  private String lastName;
  public Student(String firstName, String lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
  }
  public String getFirstName() {
    return firstName;
  }
  public void setFirstName(String firstName) {
    this.firstName = firstName;
  }
  public String getLastName() {
    return lastName;
  }
  public void setLastName(String lastName) {
    this.lastName = lastName;
  }
  public int compareTo(Student other) {
    /*
    compare the last names and save the result
    in `compareResult` variable
    */
    int compareResult = this.lastName.compareTo(other.lastName);
    /*
    If both last names match, then it would be true means 0. So,
    dive into the `if` condition and check if the count of their
    first name matches.
    if this.count == other.count return 0
    if this.count > other.count return 1
    if this.count < other.count return -1
    */
    if (compareResult == 0) {
      if (this.firstName.chars().count() == other.firstName.chars().count()) {
        compareResult = 0;
        return compareResult;
      } else if (this.firstName.chars().count() > other.firstName.chars().count()) {
        compareResult = 1;
        return compareResult;
      } else {
        compareResult = -1;
        return compareResult;
      }
    } else {
      return compareResult;
    }
  }
}
Example Code (Main.java class):
public class Main {
  public static void main(String[] args) {
    Student std1 = new Student("Mehvish", "Ashiq");
    Student std2 = new Student("Mehvish", "Ashiq");
    System.out.println("Result of Comparison 1: " + std1.compareTo(std2));
    Student std3 = new Student("Aftab", "Ashiq");
    Student std4 = new Student("Mehvish", "Ashiq");
    System.out.println("Result of Comparison 2: " + std3.compareTo(std4));
    Student std5 = new Student("Mehr-un-nissa", "Ashiq");
    Student std6 = new Student("Mehvish", "Ashiq");
    System.out.println("Result of Comparison 3: " + std5.compareTo(std6));
  }
}
OUTPUT:
Result of Comparison 1: 0
Result of Comparison 2: -1
Result of Comparison 3: 1
In this code, we compare the letter count of firstName if two objects’ lastName are the same.
As we can see, the results are consistent. If a==b, a<b, and a>b, it returns 0, -1, and 1, respectively.
Related Article - Java Error
- How to Fix the Error: Failed to Create the Java Virtual Machine
- How to Fix the Missing Server JVM Error in Java
- How to Fix the 'No Java Virtual Machine Was Found' Error in Eclipse
- How to Fix Javax.Net.SSL.SSLHandShakeException: Remote Host Closed Connection During Handshake
- How to Fix the Error: Failed to Create the Java Virtual Machine
- How to Fix Java.Lang.VerifyError: Bad Type on Operand Stack
