這期內(nèi)容當(dāng)中小編將會給大家?guī)碛嘘P(guān)Java中hashCode()與equals()有什么不同,文章內(nèi)容豐富且以專業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。
成都創(chuàng)新互聯(lián)-專業(yè)網(wǎng)站定制、快速模板網(wǎng)站建設(shè)、高性價比岳陽縣網(wǎng)站開發(fā)、企業(yè)建站全套包干低至880元,成熟完善的模板庫,直接使用。一站式岳陽縣網(wǎng)站制作公司更省心,省錢,快速模板網(wǎng)站建設(shè)找我們,業(yè)務(wù)覆蓋岳陽縣地區(qū)。費(fèi)用合理售后完善,10余年實體公司更值得信賴。
equals()方法
equals是Object類提供的方法之一,眾所周知,每一個java類都繼承自O(shè)bject類,所以說每一個對象都有equals這個方法。而我們在用這個方法時卻一般都重寫這個方法,why?
先看一個Object類中equals()方法的源代碼:
public boolean equals(Object obj) { return (this == obj); }
從這個方法中可以看出,只有當(dāng)一個實例等于它本身的時候,equals()才會返回true值。通俗地說,此時比較的是兩個引用是否指向內(nèi)存中的同一個對象,也可以稱做是否實例相等。而我們在使用equals()來比較兩個指向值對象的引用的時候,往往希望知道它們邏輯上是否相等,而不是它們是否指向同一個對象——這就是我們通常重寫這個方法的原因。
Strings1 = new String(“kvill”),String s2 = new String(“kvill”);s1.equals(s2)為ture,
說明String類中已經(jīng)重寫了equals()方法,如果不重寫equals()方法,那么s1.equals(s2)默認(rèn)比較兩個對象所指向的內(nèi)存地址是否相同,返回值必然為false。
當(dāng)然接下來我們要改寫equals()方法,必須要遵守通用約定。來自java.lang.Object的規(guī)范,equals方法實現(xiàn)了等價關(guān)系,以下是要求遵循的5點:
1.自反性:對于任意的引用值x,x.equals(x)一定為true。
2.對稱性:對于任意的引用值x 和 y,當(dāng)x.equals(y)返回true時,y.equals(x)也一定返回true。
3.傳遞性:對于任意的引用值x、y和z,如果x.equals(y)返回true,并且y.equals(z)也返回true,那么x.equals(z)也一定返回true。
4. 一致性:對于任意的引用值x 和y,如果用于equals比較的對象信息沒有被修改,多次調(diào)用x.equals(y)要么一致地返回true,要么一致地返回false。
5.非空性:對于任意的非空引用值x,x.equals(null)一定返回false。
hashCode()方法
hashcode()這個方法也是從object類中繼承過來的,在object類中定義如下:
public native int hashCode();
hashCode()返回該對象的哈希碼值,該值通常是一個由該對象的內(nèi)部地址轉(zhuǎn)換而來的整數(shù),它的實現(xiàn)主要是為了提高哈希表(例如java.util.Hashtable提供的哈希表)的性能。
必須銘記:在每個重寫了equals方法的類中,你必須也要重寫hashCode方法。如果不這樣做的話,就會違反Object.hashCode的通用約定,從而導(dǎo)致該類無法與所有基于散列值(hash)的集合類結(jié)合在一起正常運(yùn)行。
hashCode()的返回值和equals()的關(guān)系如下:
如果x.equals(y)返回“true”,那么x和y的hashCode()必須相等。
如果x.equals(y)返回“false”,那么x和y的hashCode()有可能相等,也有可能不等。
public class TestEquals { public static void main(String args[]) { Student s1 = new Student("張一", 6); Student s2 = new Student("張一", 6); if (s1.equals(s2)) { System.out.println("相同 s1的代碼:" + s1.hashCode() + " s2的代碼:" + s2.hashCode()); } else { System.out.println("不相同"); } } } class Student { private int age; private String name; public Student() { } public Student(String name, int age) { this.age = age; this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int hashCode() { return (this.name.hashCode() + this.age) * 31; } public boolean equals(Object obj) { boolean result = false; if (obj == null) { result = false; } if (this == obj) { result = true; } if (obj instanceof Student) { Student stu = (Student) obj; if (stu.getName().equals(this.name) && stu.getAge() == (this.age)) { result = true; } } else { result = false; } return result; } }
詳細(xì)分析
equals()是判讀兩個Set是否相等[前提是equals()在類中被覆蓋]。==決定引用值是否指向同一對象。
1、當(dāng)向集合set中增加對象時,首先計算要增加對象的hashCode碼,根據(jù)該值來得到一個位置來存放當(dāng)前的對象,當(dāng)在該位置沒有一個對象存在的話,那么集合set認(rèn)為該對象在集合中不存在,直接增加進(jìn)去。如果在該位置有一個對象的話,接著將準(zhǔn)備增加到集合中的對象與該位置上的對象進(jìn)行equals方法比較,如果該equals方法返回false,那么集合認(rèn)為集合中不存在該對象,再進(jìn)行一次散列,將該對象放到散列后計算出的新地址里,如果equals方法返回true,那么集合認(rèn)為集合中已經(jīng)存在該對象了,不會再將該對象增加到集合中了。
2、當(dāng)重寫equals方法時,必須要重寫hashCode方法。在java的集合中,判斷兩個對象是否相等的規(guī)則是:
1),判斷兩個對象的hashCode是否相等
如果不相等,認(rèn)為兩個對象也不相等,完畢 ; 如果相等,轉(zhuǎn)入2
2),判斷兩個對象用equals運(yùn)算是否相等
如果不相等,認(rèn)為兩個對象也不相等
如果相等,認(rèn)為兩個對象相等(equals()是判斷兩個對象是否相等的關(guān)鍵)
可見hashcode()相等時,equals()方法也可能不等。
public static void main(String args[]){ String s1=new String("zhaoxudong"); //此語句創(chuàng)建了兩個對象,一個是字符串對象“zhaoxudong”(存放于棧中的字面量),另一個是new后在堆中產(chǎn)生的對象。詳細(xì)見下面的四.4 String s2=new String("zhaoxudong"); //上述兩條語句一共是產(chǎn)生了三個對象,因為棧中只有產(chǎn)生了一個對象。 System.out.println(s1==s2);//false System.out.println(s1.equals(s2));//true System.out.println(s1.hashCode());//s1.hashcode()等于s2.hashcode() ,指向同一內(nèi)存的引用 System.out.println(s2.hashCode()); //equals和hashCode方法只用于兩個對象的比較和容器中,與對象的創(chuàng)建沒有關(guān)系 Set hashset=new HashSet(); hashset.add(s1); hashset.add(s2); /*在添加s1,s2時, hashset認(rèn)為s1和s2是相等的,所以讓s2覆蓋了s1;*/ Iterator it=hashset.iterator(); while(it.hasNext()){ System.out.println(it.next()); } //最后在while循環(huán)的時候只打印出了一個”zhaoxudong”。
這是因為String類已經(jīng)重寫了equals()方法和hashcode()方法。
但是看下面的程序:
>public class HashSetTest { public static void main(String[] args) { HashSet hs=new HashSet(); hs.add(new Student(1,"zhangsan")); hs.add(new Student(2,"lisi")); hs.add(new Student(3,"wangwu")); hs.add(new Student(1,"zhangsan")); Iterator it=hs.iterator(); while(it.hasNext()){ System.out.println(it.next()); } } } class Student { int num; String name; Student(int num,String name) { this.num=num; this.name=name; } public String toString() { return num+":"+name; } }
輸出結(jié)果為:
1:zhangsan 1:zhangsan 3:wangwu 2:lisi
為什么hashset添加了相等的元素呢?
這是不是和hashset的原則違背了呢?回答:沒有因為在根據(jù)hashcode()對兩次建立newStudent(1,"zhangsan")對象進(jìn)行比較時,生成的是不同的哈希碼值,所以hashset把他當(dāng)作不同的對象對待了,當(dāng)然此時的equals()方法返回的值也不等。那么為什么會生成不同的哈希碼值呢?原因就在于我們自己寫的Student類并沒有重新自己的hashcode()和equals()方法
所以在比較時,是繼承的object類中的hashcode()方法,它是一個本地方法,比較的是對象的地址(引用地址),使用new方法創(chuàng)建對象,兩次生成的當(dāng)然是不同的對象了,造成的結(jié)果就是兩個對象的hashcode()返回的值不一樣。那么怎么解決這個問題呢?
原因是:在Student類中重新hashcode()和equals()方法。
class Student{ int num; String name; Student(int num,String name){ this.num=num; this.name=name; } public int hashCode(){ //重寫hashCode的方法 return num*name.hashCode(); } public boolean equals(Object o) { Student s=(Student)o; return num==s.num && name.equals(s.name); //&&的優(yōu)先級比==低,所以前面不必加括號 } public String toString(){return num+":"+name; } }
根據(jù)重寫的方法,即便兩次調(diào)用了new Student(1,"zhangsan"),我們在獲得對象的哈希碼時,根據(jù)重寫的方法hashcode(),獲得的哈希碼肯定是一樣的。所以運(yùn)行修改后的程序時,我們會看到重復(fù)元素的問題已經(jīng)消除。
上述就是小編為大家分享的Java中hashCode()與equals()有什么不同了,如果剛好有類似的疑惑,不妨參照上述分析進(jìn)行理解。如果想知道更多相關(guān)知識,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。
網(wǎng)頁標(biāo)題:Java中hashCode()與equals()有什么不同
轉(zhuǎn)載源于:http://jinyejixie.com/article2/iisiic.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站導(dǎo)航、微信小程序、定制網(wǎng)站、虛擬主機(jī)、營銷型網(wǎng)站建設(shè)、網(wǎng)站維護(hù)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)