Robby Smet
Robby Smet

Reputation: 4661

Comparison method violates its general contract in sorting method

I get an error in my sorting method.

Comparison method violates its general contract

This is my sorting object with sort method

public abstract class ComparablePerson extends IDValueItem implements
        Comparable<ComparablePerson> {

    private int score;
    private String itemID,itemName;

    //setters and getters

    public int compareTo(ComparablePerson another) {
    if (score == another.getScore())
        return this.getItemName().compareToIgnoreCase(another.getItemName());
    else if ((score) > another.getScore())
        return 1;
    else
        return -1;
}

@Override
public boolean equals(Object o) {
    final ComparablePerson other = (ComparablePerson) o; 

    if (score == other.getScore() && this.getItemName().equalsIgnoreCase(other.getItemName())) 
        return true; 
    else 
        return false; 
}

I just call Collections.sort(ComparablePersonCollection);

What can be the cause of this?

Upvotes: 0

Views: 600

Answers (2)

Aubin
Aubin

Reputation: 14863

ComparablePerson is abstract, the comparison method is probably overloaded elsewhere...

Can you post the client (which owns the collection) and the concrete classes?

This code works well:

public class ComparablePerson implements Comparable< ComparablePerson > {
   public ComparablePerson( int score, String name ) {
      _score    = score;
      _itemName = name;
   }

   @Override public int compareTo( ComparablePerson another ) {
      int delta = _score - another._score;
      if( delta != 0 ) return delta;
      return _itemName.compareToIgnoreCase( another._itemName );
   }

   @Override public boolean equals( Object o ) {
      return 0 == compareTo((ComparablePerson)o);
   }

   @Override public int hashCode() {
      return super.hashCode();
   }

   private final int    _score;
   private final String _itemName;

   public static void main( String[] args ) {
      List< ComparablePerson > oSet = new LinkedList<>();
      oSet.add( new ComparablePerson( 5, "x" ));
      oSet.add( new ComparablePerson( 5, "y" ));
      oSet.add( new ComparablePerson( 5, "z" ));
      oSet.add( new ComparablePerson( 6, "x" ));
      oSet.add( new ComparablePerson( 6, "y" ));
      oSet.add( new ComparablePerson( 6, "z" ));
      Collections.sort( oSet );
      System.err.println( "Ok" );
   }
}

Upvotes: 1

SkyWalker
SkyWalker

Reputation: 14307

The compareTo and equals method implementations seem to be inconsistent, the error is telling you that for the same two objects equals gives true while compareTo does not produce zero, which is incorrect. I suggest you invoke compareTo from equals to ensure consistency or otherwise define a custom Comparator<T>.

Simply do:

public abstract class ComparablePerson extends IDValueItem implements Comparable<ComparablePerson> {

    private int score;
    private String itemID,itemName;

    //setters and getters

    public int compareTo(ComparablePerson another) {
    if (score == another.getScore())
        return this.getItemName().compareToIgnoreCase(another.getItemName());
    else if ((score) > another.getScore())
        return 1;
    else
        return -1;
    }

    @Override
    public boolean equals(Object o) {
        return compareTo(o) == 0; 
    }   
}

Upvotes: 2

Related Questions