等价方法的传递性

时间:2011-10-08 13:45:27

标签: java

equals(object)方法的合同指定了4个要遵循的属性:自反,对称,传递和一致。虽然我理解不遵循Reflexive,Symmetric和Consistent的危险,并且肯定会同意其传递的好处,但我想知道如果违反Transitive属性会带来什么伤害?

具体来说,哪个Java库(或各种第三方库)需要依赖equals才能传递才能正常工作?根据我的理解,如果其他3个属性得到很好的实现,Collections框架将会起作用。

4 个答案:

答案 0 :(得分:41)

假设三个对象a,b,c与

a == a, b == b, c == c (reflexive)
a == b, b == a
b == c, c == b
a != c, c != a

(伪代码,x == y代表x.equals(y))。

现在,让我们将对象添加到集合中:

Set s = new HashSet(); // Set implementation doesn't matter
s.add(b); // s = [b]
s.add(a); // s doesn't change, because a == b
s.add(c); // s doesn't change, because c == b

相反,如果我们以不同的顺序添加它们:

Set s = new HashSet();
s.add(a); // s = [a]
s.add(b); // s doesn't change, because b == a
s.add(c); // s = [a,c], because c != a

这显然是违反直觉的,与人们对集合的预期行为不符。例如,这意味着两个集合的联合(即s.addAll(someOtherSet)之后的s的状态)可能取决于someOtherSet的实现(元素的顺序)。

答案 1 :(得分:9)

目前我不知道Java API存在传感性缺失的问题。 (我还在反思一个例子)。

但与此无关,平等需要及物性,因为这是平等关系的数学代数定义。 http://en.wikipedia.org/wiki/Equality_(mathematics)

如果不存在传递性,则不得将该方法称为等于,因为考虑到听到/读取“平等”时的期望,这会产生误导。这与最不惊讶的原则相矛盾。 http://en.wikipedia.org/wiki/Principle_of_least_astonishment

<强> [编辑]

关于这一点的有趣之处在于严格的数学说法java equals方法定义的“相等”不是相等而是更一般的等价关系http://en.wikipedia.org/wiki/Equivalence_relation,因为根据不同的对象也可以“相等” java,因此与真正平等所需的反对称属性相矛盾。

结论:

。Java中的.ququals是一种等价关系(仍然需要传递性)

Java中的

==是一种相等(或同一性)关系

答案 2 :(得分:1)

考虑对象a == b == c,带有!= c(非传递相等)

第一个问题是hashcode()契约,如果对象相等,则需要哈希码相等。并且您将能够将a和c添加到同一组中 - 这可能会导致意外地点的细微问题

答案 3 :(得分:1)

Integer a = new Integer(1);
Integer b = new Integer(1);

a == 1为真,b == 1为真,但a == b不正确。