如何使用 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
,因此如果添加的对象不是 Comparable
和 Comparator
未提供。没关系;如果要允许传入 Comparator
进行比较,则不能将优先级队列的类型参数限制为 Comparable
,因为 Comparator
不会以这种方式限制其类型参数.
compare
方法简单地委托给 Comparable
的 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
可以使用。它要么是传入的那个,要么是上面 class 的一个实例,它试图将对象视为 Comparable
.
built-in PriorityQueue
has constructors for creating a queue using Comparable
objects, and for creating a queue using a Comparator
:
PriorityQueue()
- 根据元素的自然顺序. 对其元素进行排序
PriorityQueue(Comparator<? super E> 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
我有兴趣在 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
,因此如果添加的对象不是 Comparable
和 Comparator
未提供。没关系;如果要允许传入 Comparator
进行比较,则不能将优先级队列的类型参数限制为 Comparable
,因为 Comparator
不会以这种方式限制其类型参数.
compare
方法简单地委托给 Comparable
的 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
可以使用。它要么是传入的那个,要么是上面 class 的一个实例,它试图将对象视为 Comparable
.
built-in PriorityQueue
has constructors for creating a queue using Comparable
objects, and for creating a queue using a Comparator
:
PriorityQueue()
- 根据元素的自然顺序. 对其元素进行排序
PriorityQueue(Comparator<? super E> 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