淺析Java中的雜湊值HashCode的作用及用法
淺析Java中的雜湊值HashCode在HashSet中的作用
0.目的
1.什麼是hashCode及如何計算。
2.hashCode在集合HashSet中的作用?
1.雜湊值如何計算
1.1沒有重寫hashCode方法
沒有重寫則會繼承父類Object中的方法,我們看一下Ojbect中的hashCode和equals
方法
public native int hashCode();//native方法
public boolean equals(Object obj) {
return (this == obj);//直接根據兩個物件的地址值來判斷是否相等
}
hashCode()
是根據記憶體地址計算Hash值
public class Test01 {
String name ="a";
int age=10;
public static void main(String[] args) {
Test01 t = new Test01();
System.out.println(t.hashCode());// 1554874502
System.out.println(System.identityHashCode(t));// 1554874502
}
}
// 若沒有重寫override方法,hashCode是根據記憶體地址計算Hash值
2.2重寫hashCode方法(idea)
以下是idea自動生成hashCode
方法,idea會同時生成equals()hashCode()
方法,
idea生成的HashCode()
方法是根據物件中的Field欄位值計算出的雜湊值
public class Test01 {
String name;
int age;
Test01(){}
Test01(String name,int age){
this.name = name;
this.age = age;
}
@Override
public boolean equals(Object o) {
if(this == o) return true;
if(o == null || getClass() != o.getClass()) return false;
Test01 test01 = (Test01) o;
if(age != test01.age) return false;
return name != null ? name.equals(test01.name) : test01.name == null;
}
@Override
public int hashCode() {
int result = name != null ? name.hashCode() : 0;
result = 31 * result + age;
return result;
}
public static void main(String[] args) {
Test01 t = new Test01();
System.out.println(t.hashCode());// 0; 由於age預設0,name預設null,故值為0
System.out.println(System.identityHashCode(t));// 1554874502
}
}
// 重寫後是根據物件中的Field欄位計算出的雜湊值
2、String中的equals和hashCode
2.1.String中hashCode方法
String的HashCode()
是通過h=31*h+val[i];迴圈計算字元的Ascii的值,最後得到的雜湊值
private int hash; // Default to 0
private final char value[]; //這是字串的字元陣列
public int hashCode() {
int h = hash;
if (h == 0 && value.length > 0) {
char val[] = value;
for (int i = 0; i < value.length; i++) {
h = 31 * h + val[i];
}
hash = h;
}
return h;
}
// String的HashCode是通過h=31*h+val[i];迴圈計算字元的Ascii的值,最後得到一個隨機數,稱為雜湊值,計算方式如下:
// "a":97
// "aA":97*31+65=3072
// "aAa":(97*31+65)*31+97=95329
2.2.String中的equals方法
String中的equals()
方法目的是比較兩個物件的值是否相等
public boolean equals(Object anObject) {
if (this == anObject) { // 若地址值相等,則直接返回true
return true;
}
if (anObject instanceof String) {// 判斷型別是否相等
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {//判斷長度是否相等
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) { // 每個字元比較是否相等
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
3.HashSet保證元素唯一原理
HashSet底層是雜湊表結構,雜湊表保證元素唯一依賴於hashCode()和equals方法().
-
當HashSet集合儲存元素的時候,就會呼叫該元素的hashCode()方法計算雜湊值。
-
判斷該雜湊值對應的位置上,是否有相同雜湊值的元素。
-
如果該雜湊值對應的位置上沒有相同雜湊值的元素,那麼就直接儲存。
-
如果該雜湊值對應的位置上有相同雜湊值的元素,那麼就產生了雜湊衝突。
-
如果產生了雜湊衝突,就得呼叫該元素的equals()方法與該雜湊值位置上的所有元素進行一一比較:
如果該雜湊值位置上有任意一個元素與該元素相等,那麼就不儲存
如果該雜湊值位置上所有元素與該元素都不相等,那麼就直接儲存
HashSet在JDK1.8之前是由雜湊表+陣列+連結串列實現,1.8之後是由雜湊表+陣列+紅黑樹實現。
// HashSet的put方法中,根據雜湊值來判斷陣列索引的位置
if ((p = tab[i = (n - 1) & hash]) == null)//(n-1)&hash等效於hash % n,轉換為陣列索引
tab[i] = newNode(hash, key, value, null);//此位置沒有元素,直接儲存
在這個陣列的每個索引上雜湊值是不等的,每個連結串列中元素雜湊值可能相等,這樣插入資料就可以減少比較次數。
3.總結
1.hashCode是根據物件的Field欄位來計算出一個int型別的值,即雜湊值
2.equals是用來比較兩個物件是否相等,若兩個物件的型別,欄位都相等則相等
這是兩個概念。
-
兩個物件equals相等,則說明兩個物件的Field欄位相等,那麼根據Field計算出來hashCode的也相等。【前提是沒有重寫這兩個方法,或者同時重寫了這兩個方法】
-
兩個物件hashCode相等,則這兩個物件equals相等。【根據hashCode的計算方式就知道不能保證相等的】
3.hashCode()最重要的目的就是:無論何時,對同一個物件呼叫hashCode()都應該產生同樣的值(參考連結中大佬的文章寫的很清晰)
相關文章
- Java 物件的雜湊值是每次 hashCode() 方法呼叫重計算麼?Java物件
- 淺析雜湊演算法演算法
- js 雜湊雜湊值的模組JS
- -XX:PretenureSizeThreshold的預設值和作用淺析
- Hashcode的作用
- 淺析MySQL replace into 的用法MySql
- java中的hashCodeJava
- 淺析java中的IO流Java
- 雜湊對映用法及演算法例題演算法
- 淺析 App_KEY 的作用APP
- 淺析TCP協議中的疑難雜症TCP協議
- java中的JAR檔案淺析JavaJAR
- 淺析反向代理的原理與作用
- 淺析線上代理IP的用法
- 淺析number型別的值型別
- 淺析Java中的執行緒池Java執行緒
- 淺析程式碼圈複雜度及認知複雜度複雜度
- 淺析企業運用,大資料管理的特點及作用!大資料
- 淺析Java併發中的單例模式Java單例模式
- Java 集合中的排序演算法淺析Java排序演算法
- Git SHA-1 雜湊值Git
- 雜湊表的程式碼實現(Java)Java
- mysql中雜湊索引的使用限制MySql索引
- 雜湊索引在MySQL中的探究索引MySql
- 安全的雜湊
- 2021-2-17:Java HashMap 的中 key 的雜湊值是如何計算的,為何這麼計算?JavaHashMap
- JAVA面試題 淺析Java中的static關鍵字Java面試題
- Hash,雜湊,雜湊?
- JAVA 實現 - 雜湊表Java
- C++ remove erase 用法淺析C++REM
- [PHP核心探索]PHP中的雜湊表PHP
- 淺析Java反射--JavaJava反射
- 雜湊表的原理
- 容器中Java 程式OOMKilled原因淺析JavaOOM
- 淺析賦值、淺拷貝、深拷貝的區別賦值
- 如何正確實現 Java 中的 HashCodeJava
- Java類的生命週期淺析Java
- 在Java中,HashMap中是用哪些方法來解決雜湊衝突的?JavaHashMap