2011-10-08 24 views
30

equals(object)方法的合同指定了以下4个属性:自反,对称,传递和一致。虽然我理解不遵循自反,对称和一致的危险,并且可以肯定它遵循传递的好处,但我想知道如果违反传递属性会带来什么危害?等价方法的传递性质

具体而言,Java库(或各种第三方库)中的哪一个需要依赖于equals以传递正确工作?根据我的理解,如果其他3个属性都得到很好的实施,则集合框架将起作用。

回答

40

假设三个对象一,b,C与

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

(伪代码,x == y斯坦ds代表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的状态)可以取决于某个其他集合的实现(元素的顺序)。

+0

这是一个真正的好:)虽然你宁愿要写在第一个块“.equals”而不是“==”;) – Gandalf

+2

@Gandalf我不会。使它比我想象的更加复杂和复杂得多)好例子。 – Voo

+1

@Gandalf好了,写了'equals'。我明白为什么这些Java人将它抛弃了,但它并不能使代码可读。等价关系的标准是语言无关的。 – phihag

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也是“相等的”,因此与真正的平等所需的反对称属性相矛盾。

结论:

.equals在Java是一个等价关系(其仍需要传递性)

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

1

考虑对象A == b == c。与一!= C(非传递等同)

第一个问题是其需要散列码是相等的,如果对象是相等的哈希码()的合同。而你,也就能够a和c添加到同一组 - 这会导致微妙的问题在意想不到的地方

+3

'hashCode'不是一个问题:'int hashCode(){return 0;}'满足含义'x == y⇒x.hashCode()== y.hashCode )'。 – phihag

+3

我不明白为什么这是一个问题。如果a == b和b == c,那么a和b具有相同的哈希码,并且b和c具有相同的哈希码,所以a和c具有相同的哈希码。只是因为!= c并不意味着它们不能共享散列码。 –

+0

在听到@joshbloch的一些演讲后(他在java和其他事情中开发了很多集合框架),我在写hashCode和equals时非常谨慎 - 打破他们的合同可能会导致非常奇怪的结果 –

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

a == 1是真实的,b == 1是真实的,但,a == b是不正确的。

+0

既不回答问题也不解释一些东西。 –

+0

Java是唯一具有我知道的基本类型框语言的语言。而我从来没有看到另一种语言使得1!= 1发生,不是python,不是javascript,不是c#,不是c,不是,不会生锈。 – TimYi