摘要:如果我們不重寫的方法,那么就會默認調用的方法小王小王我們可以看到以上的運行結果違背了的規定如果返回,那么方法必須返回相同的整數所以我們需要對對象的方法進行重寫通過重寫讓其與對象的屬性關聯起來,那么就能夠達到為,那么的值也相等。
面試官讓你說說==和equals()的區別,重寫equals必須重寫hashcode方法嗎
本身特質來說
==:操作符
equals():方法
適用對象
==:主要用于基本類型之間的比較(char、Boolean、byte、short、int、long、float、dobule),也可以用于比較對象
equals():對象之間的比較(基本類型的包裝器類型,string,自己定義的對象等)
比較對象時的區別
==:比較兩個對象是否指向同一個對象,也就是說他們指向的對象的首地址是否相同
equals():可以通過重寫equals方法從而比較對象的內容是否相同,如果不重寫那么和==符號沒有區別,都是比較的對象的引用是否指向同一個對象
對于一個對象student來說,如果我們不重寫它的equals方法,那么和==符號一樣比較的是對象的引用而不是內容
public class Student { private int id; private String name; private String password; public Student(int id, String name, String password) { this.id = id; this.name = name; this.password = password; } }
public class Test2 { public static void main(String[] args){ Student s1 = new Student(1, "小王", "123456"); Student s2 = new Student(1, "小王", "123456"); System.out.println(s1 == s2);//false System.out.println(s1.equals(s2));//false } }
上面兩個對象s1和s2不相等,因為他們指向的是兩個不同的對象,所以引用不同,但是我們的目的是要達到如果id,name,password都相同,那么就是同一個對象,所以需要重寫equals()方法
@Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Student student = (Student) o; if (id != student.id) return false; if (name != null ? !name.equals(student.name) : student.name != null) return false; return password != null ? password.equals(student.password) : student.password == null; }
這個時候我們再運行
public class Test2 { public static void main(String[] args){ Student s1 = new Student(1, "小王", "123456"); Student s2 = new Student(1, "小王", "123456"); System.out.println(s1 == s2);//false System.out.println(s1.equals(s2));//true } }
對于string類型來說,它的的equals()方法是對object方法的equals()進行了重寫,從而比較的字符串序列是
否相同如下:
String s1 = new String("abc");//s1存在于堆內存中 String s2 = new String("abc");//s2也存在于堆內存中 System.out.println(s1 == s2);//false s1和s2指向的對象的首地址不一樣,不是同一個對象 System.out.println(s1.equals(s2));//true s1和s2指向的對象的內容相同
ps:
String s3 = "abc"; String s4 = "abc"; System.out.println(s3 == s4);//true System.out.println(s3.equals(s4));//true
接下來我們討論一下重寫equals()方法的同時必須要重寫hashcode()方法嗎
? 首先我們重寫equals()的目的就是為了讓內容相同的對象讓它們相同,而不是單單只比較對象的引用(對象的首地址),也就是盡管這兩個對象的引用地址不同,但是我們調用equals方法的時候仍然返回true
? 那么這個時候我們為什么又要重寫hashcode方法呢,hashcode()返回的是對象的地址,是一個散列值,那么如果我們通過equals()方法得到這兩個對象相同,盡管他們在堆中的內存地址不一樣,但是我們希望他們的哈希值是一樣的,這樣如果存入map的話,就能定位到相同的索引
? 同時Java標準中對hashcode有如下的規定:
在java應用程序執行期間,如果在equals方法比較中所用的信息沒有被修改,那么在同一個對象上多次調用hashCode方法時必須一致地返回相同的整數。如果多次執行同一個應用時,不要求該整數必須相同。
如果兩個對象通過調用equals方法是相等的,那么這兩個對象調用hashCode方法必須返回相同的整數。
如果兩個對象通過調用equals方法是不相等的,不要求這兩個對象調用hashCode方法必須返回不同的整數。
如果我們不重寫student的hashcode()方法,那么就會默認調用object的hashcode()方法:
public class Test2 { public static void main(String[] args){ Student s1 = new Student(1, "小王", "123456"); Student s2 = new Student(1, "小王", "123456"); System.out.println(s1 == s2);//false System.out.println(s1.equals(s2));//true System.out.println(s1.hashCode());//356573597 System.out.println(s2.hashCode());//1735600054 } }
我們可以看到以上的運行結果違背了hashcode的規定:如果equals()返回true,那么hashcode方法必須返回相同的整數
所以我們需要對student對象的hashcode方法進行重寫
@Override public int hashCode() { int result = id; result = 31 * result + (name != null ? name.hashCode() : 0); result = 31 * result + (password != null ? password.hashCode() : 0); return result; }
通過重寫hashcode()讓其與對象的屬性關聯起來,那么就能夠達到equals()為true,那么hashcode的值也相等。
現在我們已經知道了重寫equals()方法的同時需要重寫對象的hashcode()方法,讓其滿足hashcode的標準條件。
? 但是好奇的同學可能會想到:為什么hashcode需要這樣定義標準呢,這樣做到底有什么好處呢,除了讓equals()方法和hashcode()方法的返回值具有一致性。
這時我們就需要提到map類了,我們知道hashmap的結構是一個數組加鏈表組成的,我們通過key的
? hashcode % hashmap的capacity 定位到具體數組的索引,然后將該(key,value)放入該索引對應的鏈表里面,這里之所以為鏈表就是為了解決hash沖突,即hashcode % capacity 相同的值有很多,需要用一個鏈表存儲起來,如果想要鏈表短一點,也就是hash沖突少一點,那么就需要減小hashmap的負載因子loadFacotor,當然這里也就扯遠了,我們繼續回到正題,
Student s1 = new Student(1, "小王", "123456"); Student s2 = new Student(1, "小王", "123456");
? 對于s1和s2兩個對象,如果我們我們已經將s1存入一個map對象,那么我們再存入s2時,我們希望的是這是不能再插入map了,因為此時map中已經存在小王這個對象了,那么如何才能做到呢
? 首先我們通過s1的hashcode % capacity 得到了一個數組索引,然后將s1這個對象存入map,那么我們再插入s2的時候同樣也需要計算它的hashcode,然后定位到相同的數組索引,然后判斷該鏈表中是否存在小王這樣一個對象,如果存在就不put
? 所以我們需要得到的s1和s2的hashcode相同,才能避免同一個對象被put進入map中多次,所以我們才需要在重寫equals()方法的同時重寫equals()方法,讓兩個相等的對象具有相同的hashcode
? 可能細心的盆友會發現如果我們只是需要簡單的根據判斷兩個對象的內容是否相同來判斷兩個對象是否相等,而不涉及到ma"p操作,那么其實也是不用重寫ha"shcode方法了,但是萬一哪天突然不小心放進了map了呢,所以一般我們重寫equals()方法的同時都會重寫hashcode(),確保萬無一失~
參考
重寫equal()時為什么也得重寫hashCode()之深度解讀equal方法與hashCode方法淵源
重寫equals方法后重寫hashCode方法的必要性
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/77773.html
摘要:介紹的作用是獲取哈希碼,也稱為散列碼它實際上是返回一個整數。所以具有相索引的對象,在該散列碼位置處存在多個對象,我們必須依靠的和本身來進行區分。 1.hashCode介紹 hashCode() 的作用是獲取哈希碼,也稱為散列碼;它實際上是返回一個int整數。這個散列碼的作用是確定該對象在散列表中的索引位置,如果有看我的上一篇文章 什么是散列表,那么這里的散列碼就相當于上文中根據首字母查...
摘要:中,任何未處理的受檢查異常強制在子句中聲明。運行時多態是面向對象最精髓的東西,要實現運行時多態需要方法重寫子類繼承父類并重寫父類中已 1、簡述Java程序編譯和運行的過程:答:① Java編譯程序將Java源程序翻譯為JVM可執行代碼--字節碼,創建完源文件之后,程序會先被編譯成 .class 文件。② 在編譯好的java程序得到.class文件后,使用命令java 運行這個 .c...
摘要:中,任何未處理的受檢查異常強制在子句中聲明。運行時多態是面向對象最精髓的東西,要實現運行時多態需要方法重寫子類繼承父類并重寫父類中已 1、簡述Java程序編譯和運行的過程:答:① Java編譯程序將Java源程序翻譯為JVM可執行代碼--字節碼,創建完源文件之后,程序會先被編譯成 .class 文件。② 在編譯好的java程序得到.class文件后,使用命令java 運行這個 .c...
摘要:最近看到上面的一篇博客面試必備最常見的面試題全解析講解了關于體系的一些模塊以及面試中的一些常見問題雖然最近沒有要去找工作的需求但是鞏固一下這方面的知識還是很有必要的后面從作者提出的問題進行自我的提問與解答有問題歡迎大家指出基礎部分和的區別我 最近看到CSDN上面的一篇博客 面試必備:《Java最常見的200+面試題全解析》, 講解了關于Java體系的一些模塊以及面試中的一些常見問題; ...
摘要:在中對象是一切對象都會自動繼承的一個類,在這個類中定義的屬性和方法可以說是每個類都必須的。這里有必要說說這里對象里面的幾個方法返回該對象的哈希碼值。這些基于表的集合,只能要求被存放的對象實現自己的方法,保證的均勻性。 Object 在Java中Object對象是一切對象都會自動繼承的一個類,在這個類中定義的屬性和方法可以說是每個類都必須的。 這里有必要說說這里對象里面的幾個方法 has...
閱讀 1868·2021-11-22 09:34
閱讀 1141·2021-10-09 09:44
閱讀 3001·2021-09-29 09:35
閱讀 3617·2021-09-14 18:01
閱讀 1465·2021-08-16 10:49
閱讀 1084·2019-08-29 14:11
閱讀 849·2019-08-29 12:47
閱讀 3068·2019-08-26 13:47