Giovanni Azua Giovanni Azua - 1 year ago 62
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 Source

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.