如何重写hashCode()和equals()方法

hashCode()和equals()方法可以说是Java完全面向对象的一大特色．它为我们的编程提供便利的同时也带来了很多危险．这篇文章我们就讨论一下如何正解理解和使用这２个方法．

如何重写equals()方法

• It isreflexive: for any non-null reference valuex,x.equals(x)should returntrue.
• It issymmetric: for any non-null reference valuesxandy,x.equals(y)should returntrueif and only ify.equals(x)returnstrue.
• It istransitive: for any non-null reference valuesx,y, andz, ifx.equals(y)returnstrueandy.equals(z)returnstrue, thenx.equals(z)should returntrue.
• It isconsistent: for any non-null reference valuesxandy, multiple invocations ofx.equals(y)consistently returntrueor consistently returnfalse, provided no information used inequalscomparisons on the objects is modified.
• For any non-null reference valuex,x.equals(null)should returnfalse.

1. 自反性：A.equals(A)要返回true.
2. 对称性：如果A.equals(B)返回true, 则B.equals(A)也要返回true.
3. 传递性：如果A.equals(B)为true, B.equals(C)为true, 则A.equals(C)也要为true. 说白了就是 A = B , B = C , 那么A = C.
4. 一致性：只要A,B对象的状态没有改变，A.equals(B)必须始终返回true.
5. A.equals(null) 要返回false.

class Coder {
private String name;
private int age;

// getters and setters
}

1. 判断是否等于自身.
if(other == this)
return true;
2. 使用instanceof运算符判断 other 是否为Coder类型的对象.
if(!(other instanceof Coder))
return false;
3. 比较Coder类中你自定义的数据域，name和age，一个都不能少.
Coder o = (Coder)other;
return o.name.equals(name) && o.age == age;

如何重写hashCode()方法

Note that it is generally necessary to override the hashCode method whenever this method（equals） is overridden, so as to maintain the general contract for the hashCode method, which states that equal objects must have equal hash codes.＂

＜Effective Java＞中给出了一个能最大程度上避免哈希冲突的写法，但我个人认为对于一般的应用来说没有必要搞的这么麻烦．如果你的应用中HashSet中需要存放上万上百万个对象时，那你应该严格遵循书中给定的方法．如果是写一个中小型的应用，那么下面的原则就已经足够使用了：

@Override
public int hashCode() {
int result = 17;
result = result * 31 + name.hashCode();
result = result * 31 + age;

return result;
}

"Returns a hash code for this string. The hash code for aStringobject is computed as
 s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]

using int arithmetic, where s[i] is the i th character of the string, n is the length of the string, and ^ indicates exponentiation. (The hash value of the empty string is zero.)"

重写equals()而不重写hashCode()的风险

Coder c1 = new Coder("bruce", 10);
Coder c2 = new Coder("bruce", 10);

@Override
public boolean equals(Object other) {
System.out.println("equals method invoked!");

if(other == this)
return true;
if(!(other instanceof Coder))
return false;

Coder o = (Coder)other;
return o.name.equals(name) && o.age == age;
}

Set<Coder> set = new HashSet<Coder>();
set.add(c1);

System.out.println(set.contains(c2));

c1和c2的name和age都是相同的，为什么我把c1放到HashSet中后，再调用contains(c2)却返回false呢？这就是hashCode()在作怪了．因为你没有重写hashCode()方法，所以HashSet在查找c2时，会在不同的bucket中查找．比如c1放到05这个bucket中了，在查找c2时却在06这个bucket中找，这样当然找不到了．因此，我们重写hashCode()的目的在于，在A.equals(B)返回true的情况下，A, B 的hashCode()要返回相同的值

我让hashCode()每次都返回一个固定的数行吗

@Override
public int hashCode() {
return 10;

}

07-02 1万+
01-06 2330

05-23 2万+
02-15 1万+
08-05 9236
05-24 5万+
04-07 1440