Search code examples
javacomparatorcomparable

Why use a nested class to implement Comparator?


Going through docjar for String, I happened to see the following piece of code:

public static final Comparator<String> CASE_INSENSITIVE_ORDER
                                         = new CaseInsensitiveComparator();

private static class CaseInsensitiveComparator
                       implements Comparator<String>, java.io.Serializable {
    // use serialVersionUID from JDK 1.2.2 for interoperability
    private static final long serialVersionUID = 8575799808933029326L;

    public int compare(String s1, String s2) {
        // ...
    }
}

My question is, why can't we just implement Comparator, like Comparable, and use a private method rather than a nested class?

Also on a side note, why doesn't Comparator have a method with a single parameter similar to compareTo in Comparable?


Solution

  • My question is why cannot we just implement comparator, just like comparable and use a private function rather than inner class ?

    Well (pretty much) the whole point of the Comparator interface is that an implementation of the interface is a separate class to the class of the objects being compared.

    In theory you could do what you are suggesting, but the net result is counter-intuitive

    public class MyKey implements Comparator<MyKey> {
        private String field;
    
        public boolean compare(MyKey m1, MyKey m2) {
            // We must ignore this.field!  We are comparing m1 and m2 ...
            return m1.field.compareTo(m2.field);
        }
    }
    
    MyKey[] keys = ...
    Arrays.sort(keys, new MyKey());  // Note we have to pass an instance
                                     // to provide the Comparator.
    

    In addition to being a bit counter-intuitive, your idea is limited in the sense that MyKey can only "provide" one comparator this way.

    Frankly, if you are going to do this, it makes more sense to have MyKey implement Comparable<MyKey>.


    Suppose that they had implemented String the way you proposed. Then this ...

       String[] strings = new String[]{"a", "c", "B"};
       Arrays.sort(strings);
    

    ... means sort case sensitive, but ...

       String[] strings = new String[]{"a", "c", "B"};
       Arrays.sort(strings, "weasel");
    

    ... would mean sort case insensitive. Does that really strike you as a good idea? Really?