Object型別新增操作判讀
第一步:程式首先建立一個Object泛型的Set陣列,這裡用到了上轉型;
第二步:執行object裡面的add新增方法,傳進的值為“JAVA”;
首先HashSet原始碼中會有HashSet的無參構造方法:說明只要建立一個HashSet陣列就會預設建立一個HashMap陣列
因為Set的add方法被HashSet重寫過,所以執行時add會執行HashSet的add方法,此時我們開啟HashSet中add方法:
此時引數e為剛剛傳進的”JAVA“。
可以看到add方法呼叫的map裡面的put方法,傳入e和一個常量(常量全大寫),判斷是不是null(空)。
此時我們進入map裡的put方法:
此時可以看到put需要的引數為key值和value對應剛剛傳入的e和一個常量,此時可以看到put裡面呼叫的是putVal方法,
傳入的值為hash(key),key,value,false,true。此時開啟引數列表中hash(key)方法來檢視hash(key)的值到底是個什麼樣的值:
hash方法傳進來的引數為key為e也就是”JAVA“,這裡為三目運算,若為空返回0,不為空返回一個”JAVA“特定的hashCode然後在被處理的值
此時搞明白引數列表我們就需要檢視putVal方法體:
引數hash,key,value,onlyIfAbsent,evict
其中hash隨你key引數變化而變化,key為你要存入的資料(”JAVA“),後三位為常量 false true;
第一步 建立tab,p陣列和int型別的n和i:
進入判斷語句
將table地址值賦值給tab ,table為一個全域性變數預設值為null,而且後邊判斷條件也成立,直接進入方法體
此時需要進入resize方法:
oldTab為空陣列,oldCap為0,oldThr為0,建立兩個變數為0;
隨後經過判斷預計進入:
此時newCap為16,作用為陣列預設容量初始為16;後面常量為16;newThr為16*0.75作用為0.75倍擴容
此後進入
下一步:
長度為16的陣列,下一步返回
長度為16的空陣列,此時走完resize()方法,回到putVal
此時n為16此時進入下一不判斷語句:
用來判斷tab中i = (n - 1) & hash]位元素是否為空,此時為空,賦給tab中i為元素為newNode,newNode方法體為:
此時tab第i為有值了,然後程式接著走:
最後返回一個null給呼叫它的put方法:
put也返回null給呼叫它的方法add:
判斷為true,此時返回給objects陣列true新增成功:
到此新增程式結束。
第二次新增第二個if成立進入:
不成立進入else
先進入如圖if判斷,判斷上一個不為空的hash值與這個要新增的hash值是否相等,經過hash原始碼可知為相等並且,Object的equals方法比較的記憶體地址也相等,因為沒new物件,都在一個常量池中,所以成立把p賦給e:下一步進入
因為e不為空(null),所以賦值給oldValue為一個常量PRESENT,返回給put,put返回給add:
因為PRESENT不等於null,所以返回給objects.add("JAVA");的值為false:
此時新增失敗,正好印證了HashSet不能新增重複元素的特性。