2016-05-23 65 views
1

我有一个我想放在TreeSet中的类,它实现了Comparable来按优先级对它们进行排序。下面是一小部分:从Java TreeSet中消失的对象

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。在添加两个不同的对象后,该组的大小保持为1.

我不应该使用TreeSet

回答

3

The API docs for TreeSet包含这些重要的信息:

注意,由一组(无论是否提供了明确的比较器)保持的顺序必须是符合等于如果是要正确实现Set接口。 [012]这是因为Set接口是根据equals操作定义的,但TreeSet实例使用其compareTo(或compare)方法执行所有元素比较,因此通过此方法认为相等的两个元素是,从集合的角度来看,平等。

换句话说,一个TreeSet可容纳您PacketListener类的多个实例,但只只要各自具有比所有其他不同的优先级,从而为每对元件 ,其中恰好有一个是:A == BA.compareTo(B) != 0

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

1

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

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

0

A Set是独特元素的集合。由于您使用优先级来比较PacketListener,因此我假定您最多只有五个实例TreeSet,每个优先级一个。

如果结构允许,您可以找到一个辅助键来比较PacketListener,以防它们具有相同的优先级。如果你不能,那么TreeSet是错误的路要走。