关于equals和hashcode方法
首先聲明一下,這篇文章僅僅討論引用類型
所有引用類型都是繼承自O(shè)bject類,Object類有兩個(gè)重要的方法:equals(),hashCode()經(jīng)常被使用,雖然表面上你可能看不到你的代碼里使用hashcode()。
Object類是這樣實(shí)現(xiàn)equals方法的:
1 public boolean equals(Object obj) { 2 return (this == obj); 3 }可見(jiàn)默認(rèn)情況下==和equals()方法是一樣的,即比較兩個(gè)對(duì)象的地址。
從技術(shù)上來(lái)說(shuō),只要是通過(guò)new創(chuàng)建出來(lái)的實(shí)例,任何情況下equals和==都是false;
從業(yè)務(wù)上來(lái)說(shuō),有的時(shí)候我們希望即使不是同一個(gè)實(shí)例也可以相等:比如在系統(tǒng)中的不同組件之間,可以傳遞具有相同身份證信息的人的不同實(shí)例,但是在各個(gè)組件看來(lái),這些不同實(shí)例對(duì)應(yīng)的應(yīng)該是同一個(gè)人,因?yàn)樗麄兙哂邢嗤纳矸葑C信息!
所以在開發(fā)過(guò)程中就產(chǎn)生了==不相等但是需要equals相等的矛盾!(因?yàn)?#61;=我們無(wú)法改變,所以業(yè)務(wù)邏輯只能寄希望于改變equals的實(shí)現(xiàn))。
以身份證為某個(gè)人唯一標(biāo)示作為例子,我們定義的時(shí)候應(yīng)該是這樣的:
1 /** 2 * 具有相同身份證信息的人就是同一個(gè)人 3 * 4 * @author Lucifer 5 * 6 */ 7 public class Person { 8 9 private String name; 10 private String identityCard; 11 12 public Person(String name, String identityCard) { 13 this.name = name; 14 this.setIdentityCard(identityCard); 15 } 16 17 public String getName() { 18 return name; 19 } 20 21 public void setName(String name) { 22 this.name = name; 23 } 24 25 public String getIdentityCard() { 26 return identityCard; 27 } 28 29 public void setIdentityCard(String identityCard) { 30 this.identityCard = identityCard; 31 } 32 33 @Override 34 public boolean equals(Object obj) { 35 if (obj == null) { 36 return false; 37 } 38 if (!(obj instanceof Person)) { 39 return false; 40 } 41 Person person = (Person) obj; 42 43 return person.getIdentityCard().equals(this.identityCard); 44 45 } 46 } Person類說(shuō)到這里終于可以進(jìn)入正題了,因?yàn)槲覀冇辛诵枰淖僥quals規(guī)則的需求。Object的hashcode有一些規(guī)約:
Returns a hash code value for the object. This method is supported for the benefit of hashtables such as those provided by java.util.Hashtable.
The general contract of hashCode is:
- Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application.
- If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.
- It is not required that if two objects are unequal according to the java.lang.Object.equals(java.lang.Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hashtables.
As much as is reasonably practical, the hashCode method defined by class Object does return distinct integers for distinct objects. (This is typically implemented by converting the internal address of the object into an integer, but this implementation technique is not required by the JavaTM programming language.)
紅色字體部分經(jīng)常被面試官問(wèn)道,所以不管你想不想真正理解,你都應(yīng)該記住:
1.如果兩個(gè)object通過(guò)equals方法判斷為相等,那么hashcode方法必須返回相同的整型值。
2.如果兩個(gè)object通過(guò)equals方法判斷為不相等,那么hashcode方法不要求必須返回不相等的整型值。但是程序員應(yīng)該為不相等(通過(guò)equals方法判斷的)的object返回不同的hashcode,以提高h(yuǎn)ashtables的性能。
這是我們就想到這個(gè)跟HashTable有什么關(guān)系呢,雖然沒(méi)有強(qiáng)制不相等的時(shí)候重寫hashCode方法,但是建議我們重寫以提高HashTable的性能。
那么如何重寫hashCode呢?
最簡(jiǎn)單的方法:如果你使用Eclipse開發(fā),那么在需要重寫hashCode和equals的類中右鍵選擇source->Generate hashcode and equals
上面我們的例子用這個(gè)方法生成的代碼如下:
1 /** 2 * 具有相同身份證信息的人就是同一個(gè)人 3 * 4 * @author Lucifer 5 * 6 */ 7 public class Person { 8 9 private String name; 10 private String identityCard; 11 12 public Person(String name, String identityCard) { 13 this.name = name; 14 this.setIdentityCard(identityCard); 15 } 16 17 public String getName() { 18 return name; 19 } 20 21 public void setName(String name) { 22 this.name = name; 23 } 24 25 public String getIdentityCard() { 26 return identityCard; 27 } 28 29 public void setIdentityCard(String identityCard) { 30 this.identityCard = identityCard; 31 } 32 33 @Override 34 public int hashCode() { 35 final int prime = 31; 36 int result = 1; 37 result = prime * result 38 + ((identityCard == null) ? 0 : identityCard.hashCode()); 39 result = prime * result + ((name == null) ? 0 : name.hashCode()); 40 return result; 41 } 42 43 @Override 44 public boolean equals(Object obj) { 45 if (this == obj) 46 return true; 47 if (obj == null) 48 return false; 49 if (getClass() != obj.getClass()) 50 return false; 51 Person other = (Person) obj; 52 if (identityCard == null) { 53 if (other.identityCard != null) 54 return false; 55 } else if (!identityCard.equals(other.identityCard)) 56 return false; 57 if (name == null) { 58 if (other.name != null) 59 return false; 60 } else if (!name.equals(other.name)) 61 return false; 62 return true; 63 } 64 } View Code如果加上一個(gè)int類型的字段age,生成的代碼如下:
1 @Override 2 public int hashCode() { 3 final int prime = 31; 4 int result = 1; 5 result = prime * result + age; 6 result = prime * result 7 + ((identityCard == null) ? 0 : identityCard.hashCode()); 8 result = prime * result + ((name == null) ? 0 : name.hashCode()); 9 return result; 10 }因?yàn)閷?duì)于基本類型他們的值就是他們的HashCode。
當(dāng)然,我們還注意到hashCode方法返回的是int類型。那按以上的實(shí)現(xiàn)方式會(huì)不會(huì)出現(xiàn)問(wèn)題呢,比如我們把a(bǔ)ge改成long:
1 @Override 2 public int hashCode() { 3 final int prime = 31; 4 int result = 1; 5 result = prime * result + (int) (age ^ (age >>> 32)); 6 result = prime * result 7 + ((identityCard == null) ? 0 : identityCard.hashCode()); 8 result = prime * result + ((name == null) ? 0 : name.hashCode()); 9 return result; 10 }對(duì)于超出int類型長(zhǎng)度的long類型,只需要做一下位移操作,保證不超出int范圍即可。
最后,奉上一段國(guó)外程序員給出的重寫hashCode方法的原則:
1) Take a prime hash e.g. 5, 7, 17 or 31 (prime number as hash, results in distinct hashcode for distinct object) 2) Take another prime as multiplier different than hash is good. 3) Compute hashcode for each member and add them into final hash. Repeat this for all members which participated in equals. 4) Return hashRead more:?http://javarevisited.blogspot.com/2011/10/override-hashcode-in-java-example.html#ixzz3YHnchQTu
轉(zhuǎn)載于:https://www.cnblogs.com/mayongsheng/p/4455570.html
總結(jié)
以上是生活随笔為你收集整理的关于equals和hashcode方法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 深入分析Php处理浮点数的问题
- 下一篇: 图片重排