views:

68

answers:

4

I need a comparator as part of a strategy pattern that can either use the natural ordering of the objects or some custom ordering. For the natural ordering case, I wrote a simple comparator:

private static class NaturalComparator<T extends Comparable<? super T>> implements Comparator<T> {
    @Override
    public int compare(T o1, T o2) {
        return o1.compareTo(o2);
    }
}

Seems simple enough, but I was wondering if anyone knew of one in the standard API. I looked at TreeMap, and it does it without such a class, so when that code was written, the apparent answer would be no, but perhaps it was added later.

+1  A: 

I am not familiar with a default comparator in Java, but obviously, Comparator to compareTo is often a mere wrapper.

There is no general of "natural ordering" in the standard API, although certain built in types, like numbers, have an implementation of compareTo which then becomes their natural ordering.

TreeMap and TreeSet and all these should throw a RuntimeException if the object you put in does not implement Comparable. Thus, for example, you could throw in strings or numbers but not another collection.

The code of TreeMap does not use a comparator if one is not available - it uses compareTo instead. To use compareTo, it does a cast to Comparable, which is the source of the exceptions.

    private int compare(K k1, K k2) {
      return (comparator==null ? ((Comparable <K>)k1).compareTo(k2)
                                : comparator.compare((K)k1, (K)k2));
  }
Uri
@Uri, by the way, in Java the Comparable implementation is called the Natural Ordering: http://www.filigris.com/products/docflex_javadoc/examples/new/java/lang/Comparable.html#compareTo%28T%29
Yishai
@Yishai: Ah. I was not aware of that. I would have assumed Java avoids the term like fire because compareTo could be have an arbitrary ordering that may not match the mathematical natural ordering or any ordering in the source domain. (e.g., the ordering of strings is not "natural" in the sense that it is not a pure natural language order)
Uri
+1  A: 

JDK does not have it, however it is called ComparableComparator and it exists in many frameworks such as Spring, Apache Commons, Hibernate and many others

eugener
FYI, Guava calls it `Ordering.natural()`.
Kevin Bourrillion
+1  A: 

I think if a class has a natural ordering, it is more usual in Java for it to implement Comparable rather than have a Comparator implementation for each class.

Thus, if the objects in question have a natural ordering defined, they must implement Comparable and have the compareTo method defined. No need to go looking for a Comparator. Most classes in java.util take either an optional Comparator if there is any specific ordering to be imposed, or simply try to call compareTo on the objects if there is no other ordering specified.

So, long story short: Implement Comparable whenever you want to impose a natural ordering on a class, only use a Comparator when you want something other than the natural ordering.

MAK
@downvoter: Please explain the reason for a downvote. It is quite possible I made a mistake or am plain wrong, but it does not help if I (or the OP) don't know what it is.
MAK
MAK, although I didn't downvote, I didn't upvote either because it evades the question. Sometimes you want a class to sort based on the strategy pattern (in my case it is a sub-sort of a larger alpha-numeric sort), so you don't want a separate code path for natural ordering (TreeMap's code is quite ugly due to not doing this, although they may have had performance reasons for doing what they did).
Yishai
I definitely agree about downvoting without a comment, though.
Yishai
@Yishai: Point taken. So, what I'm saying is: no, there is no default `Comparator` in the Colections classes - because of the reasons stated in my answer. You have to roll your own if you feel the need for it.
MAK
+4  A: 

Yes, the JDK definitely has it! Here it is:

Collections.reverseOrder(Collections.reverseOrder())

Just kidding. (But it's true. (Just don't actually use that. (Ever.)))

Kevin Bourrillion
By accepting this answer I'm not saying I would actually use it, but it is indeed the answer.
Yishai