你知道吗:
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
这是因为AbstractCollection
(HashMap$Values
继承)不会覆盖#equals()
。
你知道为什么会这样吗?
答案 0 :(得分:6)
根据Collection#equals()
的合同,Collection
没有通用的equals()方法,因此AbstractCollection
无法提供。{/ p>
请注意HashMap$Values
既不是Set也不是List,因此是窘境,从某种意义上说它不支持equals()
。
答案 1 :(得分:4)
AbstractList和AbstractSet都扩展了AbstractCollection,它们的equals()方法有不同的行为,由接口List和Set指定。 Collection的界面说:
虽然Collection界面没有添加 对一般合同的规定 对于Object.equals,程序员 实现Collection接口 “直接”(换句话说,创造一个 作为集合的类,但不是 集合或列表必须小心谨慎 如果他们选择覆盖 的Object.Equals。
所以AbstractCollection绝对不应该重写equals()。也就是说,我真的不知道为什么HashMap $ Values不会实现equals()本身。
答案 2 :(得分:0)
我不确定这是否是官方原因,但AbstractCollection避免在潜在的子类上添加语义约束。平等的语义由具体的继承数据结构的性质决定,特别是基于您的结构是否有序以及是否允许重复。
例如,考虑TreeSet,LinkedList,Bag等
顺便说一下,关于您发布的代码,值返回的实际类型是什么?这应该是具有具体实现的子类。如果在运行此代码时映射为空,则可能最终会出现不考虑两个空集相等的内容。