Codementor Events

Comparable vs. Comparator

Published Jun 07, 2017

You should favor the Comparator-interface over the Comparable-interface.

Comparision of two objects is always context specific. If you implement the Comparable-interface your class is bound to the context you defined. If you change the comparison you have to check every single usage semantically to ensure no side effects.

I prefer using the Comparator-interface to define context specific comparison without taking the burden on the class to compare. If I want to provide one or more natural order comparators I provide them to the class under comparison as public constants.

Example:

public class ComparatorExample {

  
  public static void main(String[] args) {

    List<SomeObject> list = new ArrayList<>();

    list.add(new SomeObject(1, "dhjf", "A"));
    list.add(new SomeObject(4, "ghdg", "A"));
    list.add(new SomeObject(6, "uztzt", "B"));
    list.add(new SomeObject(1, "jhgf", "C"));
    list.add(new SomeObject(3, "vbbn", "A"));
    list.add(new SomeObject(99, "cvcxc", "A"));
    list.add(new SomeObject(2, "dfdd", "G"));

    // examples
    
    Collections.sort(list, SomeObject.NATURAL);
    Collections.sort(list, LexicographicOrderByCategoryAndName.INSTANCE); 
    LexicographicOrderByName.INSTANCE.compare(new SomeObject(99, "cvcxc", "A"), new SomeObject(54, "fdjnn", "C"));
    
  }

  
  public static class SomeObject {
    
    public static Comparator<SomeObject> NATURAL = new Comparator<SomeObject>() {

      @Override
      public int compare(SomeObject arg0, SomeObject arg1) {
        return arg1.getId() - arg0.getId();
      }
      
    };
    
    private int id;
    private String name;
    private String category;
    
    
    public SomeObject(int id, String name, String category) {
      this.id = id;
      this.name = name;
      this.category = category;
    }
    
    public int getId() {
      return id;
    }
    
    public String getName() {
      return name;
    }
    
    public String getCategory() {
      return category;
    }
    
  }
  
  public static class LexicographicOrderByName implements Comparator<SomeObject> {

    public static LexicographicOrderByName INSTANCE = new LexicographicOrderByName();
    
    private LexicographicOrderByName() {
    }
    
    @Override
    public int compare(SomeObject o1, SomeObject o2) {
      return o1.getName().compareTo(o2.getName());
    }
    
  }

  
  public static class LexicographicOrderByCategoryAndName implements Comparator<SomeObject> {

    public static LexicographicOrderByCategoryAndName INSTANCE = new LexicographicOrderByCategoryAndName();

    private LexicographicOrderByCategoryAndName() {
    }
    
    @Override
    public int compare(SomeObject o1, SomeObject o2) {
      
      int c = o1.getCategory().compareTo(o2.getCategory());
      
      if (c == 0) {
        c = o1.getName().compareTo(o2.getName());
      }
      
      return c;
    }
    
  }
  
}
Discover and read more posts from Arne Lewinski
get started
post commentsBe the first to share your opinion
Show more replies