7

你知道吗 :

Map<Object,Object> m1 = new HashMap<Object, Object>();
Map<Object,Object> m2 = new HashMap<Object, Object>();
System.out.println("m1.equals(m2) = "+m1.equals(m2));
System.out.println("m1.keySet().equals(m2.keySet()) = "
            +m1.keySet().equals(m2.keySet()));
System.out.println("m1.entrySet().equals(m2.entrySet()) = "
            +m1.entrySet().equals(m2.entrySet()));
System.out.println("m1.values().equals(m2.values()) = "
            +m1.values().equals(m2.values()));

将输出:

m1.equals(m2) = true
m1.keySet().equals(m2.keySet()) = true
m1.entrySet().equals(m2.entrySet()) = true
m1.values().equals(m2.values()) = false

这是由于AbstractCollectionHashMap$Values继承自)不覆盖#equals().

你知道为什么会这样吗?

4

3 回答 3

6

根据 s 的约定Collection#equals(),s 没有通用的 equals() 方法Collection,因此AbstractCollection无法提供。

请注意,HashMap$Values它既不是 Set 也不是 List,因此是一个难题,并且在某种意义上是它不支持的原因equals()

于 2008-12-04T17:29:18.857 回答
4

AbstractList 和 AbstractSet 都扩展了 AbstractCollection,并且它们的 equals() 方法具有不同的行为,由接口ListSet指定。Collection的界面说:

虽然 Collection 接口没有对 Object.equals 的一般约定添加任何规定,但“直接”实现 Collection 接口的程序员(换句话说,创建一个是 Collection 但不是 Set 或 List 的类)必须小心如果他们选择覆盖 Object.equals。

所以 AbstractCollection 绝对不应该重写 equals()。也就是说,我真的不知道为什么 HashMap$Values 不会实现 equals() 本身。

于 2008-12-04T17:28:50.277 回答
0

我不确定这是否是官方原因,但 AbstractCollection 避免对潜在子类添加语义约束。相等的语义由具体的继承数据结构的性质决定,特别是基于你的结构是否有序以及它是否允许重复。

例如,考虑 TreeSet、LinkedList、Bag 等。

顺便说一句,关于您发布的代码,值返回的实际类型是什么?那应该是一个具有具体实现的子类。如果您在运行此代码时地图为空,那么您可能会得到一些不认为两个空集相等的东西。

于 2008-12-04T17:20:45.660 回答