java HashSet原始碼簡單剖析

2021-07-26 18:42:27 字數 1465 閱讀 6403

1. 首先明確hash演算法:

既然都是hashset集合了,肯定與hash演算法有關,我的理解就像是在查詢新華字典(雜湊表)一樣,按照拼音(雜湊值)先找到在哪頁(哪個儲存區域),再在該頁(區域)查詢。比全部遍歷提高了查詢效率。

2. hashset集合是如何保證唯一性的?

通過追溯add()方法,了解到底層為hashmap的put(k key, v value)方法,原始碼如下:

public v put(k key, v value) 

if (key == null)

return putfornullkey(value);

int hash = hash(key); //與物件的hashcode()有關

int i = indexfor(hash, table.length);//查詢hash對應的儲存區域位置

//迴圈倒序比較(先進入的最後比較)該區域的值

for (entrye = table[i]; e != null; e = e.next)

}modcount++;

addentry(hash, key, value, i);//按雜湊值新增成功

return

null;

}

很明顯,元素唯一性和儲存效率取決於物件的hashcode()和equals()方法。

3. 為什麼要重寫所裝入物件的hashcode()和equals()方法?

如果不重寫就會用繼承自object類的方法,而object.hashcode()代表物件的十進位制記憶體位址值,造成雜湊值肯定不同,都不用equals()直接導致例如兩個同名的學生物件能同時存在,無法滿足「定製的」唯一性。

但是如果重寫成如下方式了?

public

inthashcode()

把雜湊值變成一樣的(0),於是都能在乙個區域內用equals()比較物件的成員變數是否相同,如果不同則新增到集合。看起來不錯,但是就變成了遍歷物件了,效率太低。於是我們需要定製規則讓不同的物件雜湊值不同,於是與物件的成員變數關聯起來,但是簡單的成員變數的雜湊值相加的和可能會造成一樣的雜湊值,這就造成了衝突。為了盡可能區分,於是乘以乙個數,如下系統生成的hashcode():(為什麼是31?

public

inthashcode()

這樣,通過呼叫物件hashcode(),相同雜湊值的就會放在一起,然後用重寫的equals()判斷是否成員變數一致;不同的就直接加到集合中。

更進一步,我們或許可以得出這樣的結論(其實是規定):

當然,你未必要按照要求去做,但是如果你違背了上述原則就會發現在使用容器時,相同的物件可以出現在set集合中,同時增加新元素的效率會大大下降(對於使用雜湊儲存的系統,如果雜湊碼頻繁的衝突將會造成訪問效能急劇下降)。

JAVA hashset常用方法和原始碼分析

public static void main string args 其中map 的資料型別為hashmap,value值為object private transient hashmapmap hashsethashset new hashset hashset插入元素本質是對hashmap插入...

Sample CelShading原始碼簡析

ifndef celshading h define celshading h include sdksample.h using namespace ogre using namespace ogrebites class ogresampleclas port sample celshading...

MyBatis原始碼簡讀 原始碼拆分

整個mybatis原始碼大概被分為三個部分 目前基礎類 的範圍是 註解類 annotations包 繫結模組類 binding包 配置解析 builder包 快取 cache包 資料來源 datasource包 異常 exceptions包 jdbc jdbc包 日誌 logging包 io io包...