对象从Java TreeSet中消失

时间:2016-05-23 17:21:50

标签: java

我有一个课程,我想放入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吗?

3 个答案:

答案 0 :(得分:3)

The API docs for TreeSet包含以下重要信息:

  

请注意,如果要正确实现Set接口,则由集合维护的排序(无论是否提供显式比较器)必须与equals 一致。 [...]这是因为Set接口是根据equals操作定义的,但TreeSet实例使用其compareTo执行所有元素比较(或compare)方法,因此,从集合的角度来看,这种方法认为相等的两个元素是相等的。

换句话说,TreeSet可以容纳PacketListener类的多个实例,但只要每个实例具有与其他所有实例不同的优先级,以便每个元素对 A B ,恰好其中之一:A == BA.compareTo(B) != 0

如果您必须在同一个集合中容纳多个PacketListener个具有相同优先级的实例,那么您需要一个不同类型的集合。对于使用从HashSet继承的equals()hashCode()方法的类,Object非常适合,前提是这确实是所需的实例相等感。如果您想要某种关于迭代顺序的保证,也可以考虑LinkedHashSet,如果您想按优先级排序,可以考虑PriorityQueue,但是您愿意使用不同的机制来避免重复。< / p>

答案 1 :(得分:1)

TreeSetcompareTo返回0的两个对象视为等于。这意味着您在当前实现的树集中永远不会有两个具有相同优先级的对象。

解决问题的方法是让你的compareTo方法考虑你关心的所有值(即只有实际相等的对象返回0)。

答案 2 :(得分:0)

Set是一系列独特元素。当您使用优先级来比较PacketListener时,我假设您TreeSet中最多有五个实例,每个优先级都有一个实例。

如果结构允许,您可以找到比较PacketListener的辅助密钥,以防它们具有相同的优先级。如果你做不到,那么TreeSet是错误的方法。