4

考虑代码:

class A {

  private int i;

  boolean equals( Object t) {
      if (this == t)
          return true;
      if (!( t instanceof A))
          return false;
      if (this.i == t.i);
  }

}

Map<String,A> orig;
Map<String,B> dup;

我正在尝试这样做

orig.entrySet().removeAll(dup.entrySet());

我看到调用了equals方法;这总是正确的,还是可能会改为调用 compareTo?

4

7 回答 7

4

是的,它调用equals(). compareTo()只有在Set 知道它包含Comparable对象时才能使用(例如,排序集可能会这样做)。

于 2009-05-12T17:33:49.467 回答
3

这取决于实施。

例如, aHashSet将使用hashCodeand equals。ATreeSet可能会使用compareTo. 最终,只要您的类型表现得当,这无关紧要。

于 2009-05-12T17:39:44.137 回答
1

TreeSet 使用 compareTo,试试这个:

public class A {

    private int i;

    A(int i) {
        this.i = i;
    }

    @Override
    public boolean equals(Object t) {
        if (this == t)
            return true;
        if (!( t instanceof A))
            return false;
        return (this.i == ((A)t).i);
    }

    public static void main(String[] args) {
        List<A> remove = Arrays.asList(new A(123), new A(789));
        Set<A> set = new TreeSet<A>(new Comparator<A>() {
            @Override
            public int compare(A o1, A o2) {
                return o1.i - o2.i;  
                // return 0; // everything get removed
            }
        });
        set.add(new A(123));
        set.add(new A(456));
        set.add(new A(789));
        set.add(new A(999));

        set.removeAll(remove);
        for (A a : set) {
            System.out.println(a.i);
        }
        System.out.println("done");
    }
}

使 Comparator 始终返回 0,所有内容都将被删除!如果不使用 Comparator 而是实现 Comparable,也会发生同样的情况。

TreeSet 基于在 getEntry 中使用 compareTo 的 TreeMap。
在 TreeSet 的 Javadoc 中,您可以(最终)阅读:

... Set 接口是根据 equals 操作定义的,但TreeSet 实例使用其 compareTo(或 compare)方法执行所有元素比较...

[]]

于 2009-05-12T18:33:57.170 回答
1

http://java.sun.com/j2se/1.5.0/docs/api/java/util/Collection.html

“实现可以自由地实现优化,从而避免调用 equals,例如,首先比较两个元素的哈希码。”

很可能会使用 equals,但考虑到上面的陈述,您不能完全依赖 equals() 被调用。请记住,无论何时重写 equals(),重写 hashCode() 总是一个好主意。

于 2009-07-08T07:50:50.840 回答
0

我看不出在哪里使用 compareTo;Map 接口的 remove() 的 javadoc 说“更正式地说,如果此映射包含从键 k 到值 v 的映射,使得 (key==null ? k==null : key.equals(k)),则该映射已移除。” 而对于 Set 接口,它类似地表示“更正式地说,如果集合包含这样的元素,则删除元素 e 使得 (o==null ? e==null : o.equals(e))。”

请注意,removeAll() 的 javadoc 没有说明它是如何操作的,这意味着,正如其他人所说,它是一个实现细节。

在 Sun 的 Java 中,根据 Bloch 在其 Effective Java 中的说法(如果我没记错的话),它会遍历集合并调用 remove(),但他强调您绝不能假设它总是这样做的。

于 2009-05-12T18:12:02.027 回答
0

一些Set实现依赖于hashCode(例如HashSet)。这就是为什么hashCode当你覆盖时你也应该总是覆盖equals

于 2009-05-12T17:40:51.110 回答
0

我知道的 Java 库中唯一不会这样做的实现是IdentityHashMap例如, TreeMap没有合适的Comparator.

于 2009-05-12T17:43:59.310 回答