0

java.util.SetAPI 状态:

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

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

4

3 回答 3

5

如果compareToequals(应该)一致,则 TreeSet 是否使用compareToequals确定相等性都没有关系。来自 JavaDoc:

请注意,如果要正确实现 Set 接口,集合维护的顺序(无论是否提供显式比较器)必须与 equals 一致。(参见 Comparable 或 Comparator 以了解与 equals 一致的精确定义。)这是因为 Set 接口是根据 equals 操作定义的,但 TreeSet 实例使用其 compareTo(或 compare)方法执行所有元素比较,所以两个从集合的角度来看,这种方法认为相等的元素是相等的。一个集合的行为是明确定义的,即使它的顺序与equals不一致;它只是不遵守 Set 接口的一般约定。

该程序将打印“真”,即使equals总是返回假。但是这个错误实际上是 A 的compareToequals不一致,并且不是 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()));
    }
}
于 2012-11-24T12:34:08.657 回答
0

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

但是 Comparable/Comparator 接口用于决定一个元素是否大于、等于或小于其他元素。这在排序期间使用。因此,您唯一需要确保的是 equals 和 compareto 方法是一致的。

因此,比较两个对象使用 equals 方法,并在排序期间使用比较器/可比较

编辑 下面是来自 JDK 6 的方法定义;AbstractSet 的 equals 方法。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

于 2012-11-24T13:05:39.537 回答
0

TreeSet使用比较器。你知道它实际上是通过使用 map 来维护元素的吗?

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

正如你所说,集合不包含 e1.equals(e2) 这样的元素对 e1 和 e2。这就是 Comparator 有equals方法的原因。

无论我们将如何使用Set它都取决于Comparator. 如果我们使用自己的比较器,我们可以使用SetasList但通常我们不这样做。如果我们在初始化时添加自己的对象TreeSet必须通过或对象必须由ComparatorTreeSetComparable

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教程。

于 2012-11-24T13:07:20.883 回答