Giovanni Azua Giovanni Azua - 4 months ago 21
Java Question

converting Comparable from and to Comparator?

I often have a

Comparator
type while I need a
Comparable
and the other way around. Is there a reusable JDK API to convert from one another? Something along the lines of:

public static <C> Comparable<C> toComparable(final Comparator<C> comparator) {
// does not compile because Hidden can not extend C,
// but just to illustrate the idea
final class Hidden extends C implements Comparable<C> {
@Override
public int compareTo(C another) {
return comparator.compare((C) this, another);
}
};
return new Hidden();
}

public static <C extends Comparable<C>> Comparator<C> toComparator(final Class<C> comparableClass) {
return new Comparator<C>() {
@Override
public int compare(C first, C second) {
assert comparableClass.equals(first.getClass());
assert comparableClass.equals(second.getClass());
return first.compareTo(second);
}
};
}

Answer

ComparableComparator from Apache Commons Collections seems to address Comparable<T> to Comparator problem (unfortunately its not generic type-friendly).

The reverse operation is not quite possible because the Comparator<T> represents algorithm while Comparable<T> represents actual data. You will need composition of some sort. Quick and dirty solution:

class ComparableFromComparator<T> implements Comparable<T> {

    private final Comparator<T> comparator;
    private final T instance;

    public ComparableFromComparator(Comparator<T> comparator, T instance) {
        this.comparator = comparator;
        this.instance = instance;
    }

    @Override
    public int compareTo(T o) {
        return comparator.compare(instance, o);
    }

    public T getInstance() {
        return instance;
    }
}

Say you have class Foo that is not Comparable<Foo> but you have Comparator<Foo>. You use it like this:

Comparable<Foo> comparable = new ComparableFromComparator<Foo>(foo, comparator);

As you can see (especially without mixins) it's pretty ugly (and I'm not even sure if it'll work...) Also notice that comparable doesn't extend Foo, you have to call .getInstance() instead.

Comments