Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 419
JavaDeveloper Avatar asked Jan 13 '23 23:01

JavaDeveloper


2 Answers

Because a String is not a Comparator. Sure, they are indeed Comparable, but they are not "comparison functions"1 themselves: it makes no sense to have String implement Comparator.

On the other hand, CaseInsensitiveComparator is a specific comparison function, only pertaining to strings. So, it is declared as a static nested class.


1 See Comparator

like image 121
arshajii Avatar answered Jan 16 '23 01:01

arshajii


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?

like image 35
Stephen C Avatar answered Jan 16 '23 01:01

Stephen C