简体   繁体   中英

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);
            }
        };
    }

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.

Since Java 8 the Comparator interface has had a few utility default methods added that assist with deriving a comparator from a comparable.

Consider the following example of sorting users by first name.

class Person {
    String firstName;
    String lastName;
}

List<Person> people = ...
people.sort(Comparator.comparing(Person::firstName));

Comparable items can be sorted as they have a compareTo :

Collection<Comparable> items;
Collections.sort(items);

If items are not Comparable, they need a Comparator object to do the comparison:

Collections<T> items;
Collections.sort(items, comparator);

A bridging Comparator is trivial, and you did it already.

Wrapping every T item with some Comparable adapter having a Comparator, seems useless. First of all not inheritance but as field one needs to wrap the item.

public class CatorComparable<T> implements Comparable<CatorComparable<T>> {
    public T value;
    private Comparator<T> cator;

    public CatorComparable(T value, Comparator<T> cator) {
        this.value = value;
        this.cator = cator;
    }

    @Override
    public int compareTo(CatorComparable<T> other) {
        return cator.compareTo(value, other.value);
    }
}

Too much overhead.

You can obtain an instance of Comparator able to compare instance of Comparable type simply with

java.util.Comparator.naturalOrder()

see Comparator.naturalOrder()

this is a sort of conversion from Comparable to Comparator

I don't think you can really convert between them, nor does it really make sense to, since Comarable is a property of the class itself, while Comparator is an external class.

The best bet would be to write some sort of utility class that contains the underlying comparison logic (and probably have that implement Comparator ), then use that class as a part of the logic for the Comparable implementation on the class itself.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM