java.util.Set API中可能存在的错误

时间:2012-11-24 12:22:50

标签: java collections javadoc comparator

java.util.Set API声明:

  

集合不包含元素对e1和e2,使得e1.equals(e2)

但据我所知,TreeSet使用Comparable/Comparator来确定e1和e2是否重复。我错过了什么吗?

3 个答案:

答案 0 :(得分:5)

如果compareToequals(它应该)一致,则TreeSet是使用compareTo还是equals来确定相等性并不重要。来自JavaDoc:

  

注意由一组维护的排序(无论是否显式   比较器提供)必须与equals一致,如果是的话   正确实现Set接口。 (参见可比较者或比较者   对于与equals一致的精确定义。)就是这样   因为Set接口是根据equals操作定义的,   但是TreeSet实例使用它执行所有元素比较   compareTo(或compare)方法,因此两个被认为相等的元素   从该集合的角度来看,通过这种方法是相等的。该   集合的行为即使其排序不一致也是明确定义的   与...平等它只是没有遵守集合的一般合同   接口

即使equals始终返回false,此程序也会打印'true'。但是,错误可能是compareToequals与A不一致,并且不是TreeSet中的错误。

class A implements Comparable<A> {
    public int compareTo(A a) {
        return 0;
    }

    public boolean equals(Object other) {
        return false;
    }

    public static void main(String[] args) {
        TreeSet<A> set = new TreeSet<A>();
        set.add(new A());
        System.out.println(set.contains(new A()));
    }
}

答案 1 :(得分:0)

你的假设是错误的; TreeSet不使用Comparable / Comparator来确定e1是否等于e2。 Equals方法是Object类的一部分,用于确定集合的两个元素是否相同。即e1.equals(e2)

但Comparable / Comparator接口用于确定元素是否大于,等于或小于其他元素。这在分拣过程中使用。所以你唯一需要确保的是,equals和compareto方法是一致的。

所以要比较两个对象,使用equals方法,在排序过程中使用比较/可比较

修改 以下是JDK 6的方法定义;等于AbstractSet的方法。 TreeSet扩展了AbstractSet

    public boolean equals(Object obj)
    {
    if(obj == this)
        return true;
    if(!(obj instanceof Set))
        return false;
    Collection collection = (Collection)obj;
    if(collection.size() != size())
        return false;
    try
    {
        return containsAll(collection);
    }
    catch(ClassCastException classcastexception)
    {
        return false;
    }
    catch(NullPointerException nullpointerexception)
    {
        return false;
    }
    }

http://docs.oracle.com/javase/6/docs/api/java/util/AbstractSet.html

答案 2 :(得分:0)

TreeSet使用比较器。您是否知道它实际上通过使用map来维护元素。

 public TreeSet() {
    this(new TreeMap<E,Object>());
 }

如你所说集合不包含元素对e1和e2,使得e1.equals(e2)。这就是比较器具有equals方法的原因。

无论我们如何使用Set,都取决于Comparator。如果我们使用自己的比较器,我们可以使用Set作为List,但通常我们不会这样做。如果我们将自己的对象添加到TreeSet,则必须在初始化Comparator时通过TreeSet,或者必须通过Comparable实现对象

<强>可比  
具有与另一个对象进行比较的能力的可比较对象

比较器
用于比较两个不同的对象。

public int compare(Employee o1, Employee o2) {
    // if sort by name
    return o1.getName().compareTo(o2.getName());
 }


 public boolean equals(Object obj) {
        // equals with ID
        Employee e = (Employee)obj;
        return this.getId().equals(e.getId());
 }

以下是Java Sorting: Comparator vs Comparable教程。