我有一个课程,我想放入TreeSet
,实现Comparable
按优先顺序对它们进行排序。这是一个小部分:
public abstract class PacketListener implements Comparable<PacketListener> {
public enum ListenerPriority {
LOWEST, LOW, NORMAL, HIGH, HIGHEST
}
private final ListenerPriority priority; // Initialized in constructor
// ... class body ...
@Override
public final int compareTo(PacketListener o) {
return priority.compareTo(o.priority);
}
}
这个想法显然是TreeSet
按优先级排序对象,允许我按顺序迭代监听器。但是,我发现由于某种原因,我无法在设置对象中添加第二个PacketListener
。添加两个不同的PacketListener
对象后,集合的大小保持为1。
我不应该使用TreeSet
吗?
答案 0 :(得分:3)
The API docs for TreeSet
包含以下重要信息:
请注意,如果要正确实现
Set
接口,则由集合维护的排序(无论是否提供显式比较器)必须与equals 一致。 [...]这是因为 Set
接口是根据equals
操作定义的,但TreeSet
实例使用其compareTo
执行所有元素比较(或compare
)方法,因此,从集合的角度来看,这种方法认为相等的两个元素是相等的。
换句话说,TreeSet
可以容纳PacketListener
类的多个实例,但只要每个实例具有与其他所有实例不同的优先级,以便每个元素对 A 和 B ,恰好其中之一:A == B
或A.compareTo(B) != 0
。
如果您必须在同一个集合中容纳多个PacketListener
个具有相同优先级的实例,那么您需要一个不同类型的集合。对于使用从HashSet
继承的equals()
和hashCode()
方法的类,Object
非常适合,前提是这确实是所需的实例相等感。如果您想要某种关于迭代顺序的保证,也可以考虑LinkedHashSet
,如果您想按优先级排序,可以考虑PriorityQueue
,但是您愿意使用不同的机制来避免重复。< / p>
答案 1 :(得分:1)
TreeSet
将compareTo
返回0的两个对象视为等于。这意味着您在当前实现的树集中永远不会有两个具有相同优先级的对象。
解决问题的方法是让你的compareTo
方法考虑你关心的所有值(即只有实际相等的对象返回0)。
答案 2 :(得分:0)
Set
是一系列独特元素。当您使用优先级来比较PacketListener
时,我假设您TreeSet
中最多有五个实例,每个优先级都有一个实例。
如果结构允许,您可以找到比较PacketListener
的辅助密钥,以防它们具有相同的优先级。如果你做不到,那么TreeSet
是错误的方法。