vaibhav
vaibhav

Reputation: 329

Comparison method violates its general contract

I have implemented Comaprable on class , and it gives me Comparison method violates its general contract! , as there are some values which are returned as null , code is as follows

public static Comparator NameComparator = new Comparator() {

    public int compare(JSONReceiptList rName1, JSONReceiptList rName2) {
        if(rName1.retailer!=null || rName2.retailer!=null) {


            if(rName1.retailer==null||rName2.retailer==null) {

                return 0;
            }
            else
            {
                if(rName1.retailer.retailerName==null ||rName2.retailer.retailerName==null ) {
                    return 0;
                }
                else
                {String Name1 = rName1.retailer.getRetailerName().toUpperCase();
                    String Name2 = rName2.retailer.getRetailerName().toUpperCase();
                    return Name1.compareTo(Name2);

                }
            }
            //ascending order

        }
        else
        {
            return 0;
        }

    }

};

Upvotes: 0

Views: 147

Answers (1)

Anonymous Coward
Anonymous Coward

Reputation: 3200

Indeed it is a contract violation. From Comparator API:

It follows immediately from the contract for compare that the quotient is an equivalence relation on S, and that the imposed ordering is a total order on S.

A total order is transitive, antisymmetric, and total.

But the order imposed by your code is not transitive. If x and y have non null values and x < y but z has has null values then :

compare(x,z) = 0. compare(y,z) = 0. So, per transitive property, compare(x,y) should be zero but it is not the case.

One possible solution is to consider null values as the lowest ones.

  public int compare(JSONReceiptList rName1, JSONReceiptList rName2) {
      boolean r1IsNull = rName1.retailer==null || rName1.retailer.retailerName==null;
      boolean r2IsNull = rName2.retailer==null || rName2.retailer.retailerName==null;
      if ( r1IsNull && r2IsNull )
          return 0;
      else if ( r1IsNull  && !r2IsNull )
          return -Integer.MAX_VALUE;
      else if ( !r1IsNull && r2IsNull )
          return Integer.MAX_VALUE;
      else // Both are non null
      {
            String name1 = rName1.retailer.getRetailerName().toUpperCase();
            String name2 = rName2.retailer.getRetailerName().toUpperCase();
            return name1.compareTo(name2);
      }
  }

Upvotes: 1

Related Questions