我有兴趣在Java中实现Priority Queue的特殊变体,我希望这个优先级队列能够使用泛型类型。在Java的集合对象中存储具有某种排序的对象(例如,PriorityQueue,TreeSet等),可以使用实现Comparable的类以及不必实现Comparable的类,给定将类的Comparator传递给构造函数。
如何在Priority Queue类中实现此功能?我是否必须重写我的所有方法,具体取决于该类是否实现Comparable vs如果我被赋予Comparator?或者有没有办法从实现Comparable的类中获取Comparator,所以我只需要处理Comparator案例?
答案 0 :(得分:0)
首先,Java中的PriorityQueue
已constructors take a Comparator
。如果您尝试继承PriorityQueue
,则无需确定是否应使用Comparator
而不是Comparable
。提供调用匹配超类构造函数的构造函数。
但是,如果您要创建自己的优先级队列,那么您可以在构建优先级队列时做出一次决定。
如果提供了Comparator
,则将其存储以供日后使用。如果未提供Comparator
,则(假设Java 8+)使用Comparator.naturalOrder
的实例。
如果没有Java 8,请使用Adapter pattern实施Comparator.naturalOrder
。此适配器类T
的类型参数被限制为Comparable
,因此如果添加的对象不是ClassCastException
和Comparable
,则可能会产生Comparator
没有供应。没关系;如果要允许传递Comparable
进行比较,则不能将优先级队列的类型参数约束为Comparator
,因为Comparator
不会以这种方式限制其类型参数
compare
方法只需委托Comparable
的{{1}}方法。
compareTo
(这几乎是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
。
答案 1 :(得分:0)
内置PriorityQueue
具有使用Comparable
对象创建队列的构造函数,以及使用Comparator
创建队列的构造函数:
PriorityQueue()
- 根据自然顺序命令其元素。PriorityQueue(Comparator<? super E> comparator)
- 根据指定的比较器排序。使用类似语义实现自己的类的最简单方法是始终使用Comparator
,并且在没有提供时使用自然比较器:
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;
}
}
如果要确保在不提供Comparable
的情况下在非Comparator
的对象上创建集合时出现编译错误,则可以使用工厂方法来防范:
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