如何使用 Comparators 为 Comparable 类 和 类 编写有序集合

How to write an ordered collection for Comparable classes and classes with Comparators all in one

我有兴趣在 Java 中实现优先级队列的特殊变体,并且我希望此优先级队列与泛型一起使用。 Java 的集合对象以某种顺序存储对象(例如 PriorityQueue、TreeSet 等),可以使用实现 Comparable 的 classes 以及 class假设 class 的比较器被传递给构造函数,则不一定实现 Comparable 的 es。

如何在我的优先队列 class 中实现此功能?我是否必须根据 class 是否实现了 Comparable 以及是否为我提供了 Comparator 来重写我的所有方法?或者有没有一种方法可以从实现 Comparable 的 class 中获取 Comparator,这样我只需要处理 Comparator 的情况?

首先,Java中的PriorityQueue已经有constructors that take a Comparator。如果您尝试使用 class PriorityQueue,则无需确定您是否应该使用 Comparator 还是依赖 Comparable。提供调用匹配的 superclass 构造函数的构造函数。

但是,如果您正在创建自己的优先级队列,那么您可以在构建优先级队列时做出一次决定。

如果提供了 Comparator,则将其保存以备后用。如果未提供 Comparator,则(假设 Java 8+)使用 Comparator.naturalOrder.

的实例

没有Java 8、使用Adapter pattern实现Comparator.naturalOrder。此适配器的类型参数 class T 被限制为 Comparable,因此如果添加的对象不是 ComparableComparator 未提供。没关系;如果要允许传入 Comparator 进行比较,则不能将优先级队列的类型参数限制为 Comparable,因为 Comparator 不会以这种方式限制其类型参数.

compare 方法简单地委托给 ComparablecompareTo 方法。

class ComparableToComparator<T extends Comparable<? super T>> implements Comparator<T> {
    @Override
    public int compare(T a, T b) {
        return a.compareTo(b);
    }
}

(这几乎就是 Comparator.naturalOrder 所做的。)

无论是否传入Comparator,您都有一个Comparator可以使用。它要么是传入的那个,要么是上面 class 的一个实例,它试图将对象视为 Comparable.

built-in PriorityQueue has constructors for creating a queue using Comparable objects, and for creating a queue using a Comparator:

用相似的语义实现您自己的 class 的最简单方法是始终使用 Comparator,并在提供 none 时使用自然比较器:

public class MyOrderedCollection<E> {

    private final Comparator<? super E> comparator;

    @SuppressWarnings("unchecked")
    public MyOrderedCollection() {
        this((Comparator<? super E>) Comparator.naturalOrder());
    }

    public MyOrderedCollection(Comparator<? super E> comparator) {
        this.comparator = comparator;
    }
}

如果在不提供 Comparator 的非 Comparable 对象上创建集合时,如果您想确保得到编译错误,您可以使用工厂方法来防止这种情况发生:

public class MyOrderedCollection<E> {

    private final Comparator<? super E> comparator;

    public static <E extends Comparable<? super E>> MyOrderedCollection<E> of() {
        return new MyOrderedCollection<>(Comparator.naturalOrder());
    }

    public static <E> MyOrderedCollection<E> of(Comparator<? super E> comparator) {
        return new MyOrderedCollection<>(comparator);
    }

    private MyOrderedCollection(Comparator<? super E> comparator) {
        this.comparator = comparator;
    }
}

现在您甚至不必抑制编译警告。

有了它,它的工作原理是这样的:

MyOrderedCollection<String> x = MyOrderedCollection.of();

MyOrderedCollection<Object> y = MyOrderedCollection.of(Comparator.comparing(Object::toString));

MyOrderedCollection<Object> z = MyOrderedCollection.of(); // compilation error