導航:首頁 > 源碼編譯 > javahashmap源碼

javahashmap源碼

發布時間:2024-01-23 05:23:19

1. idea debug進入HashMap源碼時傳參不正確

我測試了下面的代碼:

綜上,jvm在啟動的時候會在程序背後隱式地將一些配置啊什麼的通過put方法放到某些地方,不用關心,你遇到的情況是正常的也是正確的

2. java查看hashmap的源碼發現並沒有向entrySet中裝入元素,而去可以如下遍歷。

幫助文檔上說:返回此映射所包含的映射關系的
collection
視圖。在返回的集合中,每個元素都是一個
Map.Entry。
entrySet僅僅是一個視圖而已,沒有具體的數據,其實還是從HashMap中獲取數據的。具體可以看entry和entrySet的源代碼就知道數據其實還是來自於table。

3. HashMap和List遍歷方法總結及如何遍歷刪除

(一)List的遍歷方法及如何實現遍歷刪除
我們造一個list出來,接下來用不同方法遍歷刪除,如下代碼:
List<String> list= new ArrayList<String>();famous.add("zs");famous.add("ls");famous.add("ww");famous.add("dz");

1、for循環遍歷list:
for(int i=0;i<list.size();i++){if(list.get(i).equals("ls"))list.remove(i);}

這是一種很常見的遍歷方式,但是使用這種遍歷刪除元素會出現問題,原因在於刪除某個元素後,list的大小發生了變化,而你的索引
也在變化,所以會導致你在遍歷的時候漏掉某些元素。比如當你刪除第一個元素後,繼續根據索引訪問第二個元素後,因為刪除的原因,
後面的元素都往前移動了以為,所以實際訪問的是第三個元素。因此,這種遍歷方式可以用在讀取元素,而不適合刪除元素。
2、增強for循環:
for(String x:list){if(x.equals("ls"))list.remove(x);}

這也是一種很常見的遍歷方式,但是使用這種遍歷刪除元素也會出現問題,運行時會報異常
其實增強for循環是java語法糖的一種體現,如果大家通過反編譯得到位元組碼,那麼上面這段代碼的內部實現如下所示:

for(Iterator<String> it = list.iterator();it.hasNext();){String s = it.next();if(s.equals("madehua")){list.remove(s);}}

下面就解釋為什麼會報異常。分析Iterator的源代碼,重點分析整個調用該過程中的
函數(hasNext和remove):

private class Itr implements Iterator<E> { int cursor; // index of next element to return int lastRet = -1; // index of last element returned; -1 if no such int expectedModCount = modCount; public boolean hasNext() { return cursor != size; // size為集合中元素的個數 } public E next() { checkForComodification(); int i = cursor; if (i >= size) throw new NoSuchElementException(); Object[] elementData = ArrayList.this.elementData; if (i >= elementData.length) throw new (); cursor = i + 1; return (E) elementData[lastRet = i]; } /* 此方法並沒被調用,只是調用List.remove方法 public void remove() { checkForComodification(); try { ArrayList.this.remove(lastRet); // size欄位減1 cursor = lastRet; lastRet = -1; expectedModCount = modCount; } catch (IndexOutOfBoundsException ex) { throw new (); } } */ final void checkForComodification() { // 檢查修改和當前版本號是否一致,不一致則拋出異常 if (modCount != expectedModCount) throw new (); } } // List.remove @Override public boolean remove(Object object) { Object[] a = array; int s = size; if (object != null) { for (int i = 0; i < s; i++) { if (object.equals(a[i])) { System.array(a, i + 1, a, i, --s - i); a[s] = null; // Prevent memory leak size = s; modCount++; // 核心代碼:修改了版本號。這樣當checkForComodification的時候,modCount值就和expectedModCount不同 return true; } } } else { for (int i = 0; i < s; i++) { if (a[i] == null) { System.array(a, i + 1, a, i, --s - i); a[s] = null; // Prevent memory leak size = s; modCount++; return true; } } } return false; }

接下來梳理一下流程,這時候你就會發現這個異常是在next方法的checkForComodification中拋出的。拋出的原因是
modCount !=expectedModCount。這里的modCount是指這個list對象從呢我出來到現在被修改的次數,當調用list
的add或者remove方法的時候,這個modCount都會自動增減;iterator創建的時候modCount被復制給了
expectedModcount,但是調用list的add和remove方法的時候不會同時自動增減expectedModcount,這樣就導致
兩個count不相等,從而拋出異常。大家如果理解了上面的執行流程,以後碰到類似這種問題,比如如果刪除的是倒數
第二個元素卻不會碰到異常。就會知道為什麼了。

3、iterator遍歷刪除:

Iterator<String> it = list.iterator();while(it.hasNext()){String x = it.next();if(x.equals("del")){it.remove();}}

這種方式是可以正常遍歷和刪除的。但是你可能看到上面代碼感覺和增強for循環內部實現的代碼差不多,其實差別就在於上面使用
一個使用list.remove(),一個使用it.remove()。

(二)HashMap的遍歷刪除及如何實現遍歷刪除
一樣我們先造一個hashmap出來,如下:

private static HashMap<Integer, String> map = new HashMap<Integer, String>();; public static void main(String[] args) { for(int i = 0; i < 10; i++){ map.put(i, "value" + i); } }

1、第一種遍歷刪除:

for(Map.Entry<Integer, String> entry : map.entrySet()){Integer key = entry.getKey();if(key % 2 == 0){System.out.println("To delete key " + key);map.remove(key);System.out.println("The key " + + key + " was deleted");}

這種遍歷刪除依舊會報異常,
2、第二種遍歷刪除:
Set<Integer> keySet = map.keySet(); for(Integer key : keySet){ if(key % 2 == 0){ System.out.println("To delete key " + key); keySet.remove(key); System.out.println("The key " + + key + " was deleted"); } }

這種遍歷刪除依舊會報異常,
3、第三種遍歷刪除:
Iterator<Map.Entry<Integer, String>> it = map.entrySet().iterator();while(it.hasNext()){Map.Entry<Integer, String> entry = it.next();Integer key = entry.getKey();if(key % 2 == 0){ System.out.println("To delete key " + key); it.remove(); System.out.println("The key " + + key + " was deleted");}}

這種遍歷是OK的
分析上述原因,如果大家理解了List的遍歷刪除,那麼感覺HashMap的遍歷刪除是不是有類似之處啊。下面就分析一下原因:
如果查詢源代碼以上的三種的刪除方式都是通過調用HashMap.removeEntryForKey方法來實現刪除key的操作。
在removeEntryForKey方法內知識一場了key modCount就會執行一次自增操作,此時modCount就與expectedModCOunt不一致了
,上面三種remove實現中,只有第三種iterator的remove方法在調用完removeEntryForKey方法後同步了expectedModCount值與
modCount相同,所以iterator方式不會拋出異常。最後希望大家遇到問題到查詢源代碼,它會給你最好的解釋!

閱讀全文

與javahashmap源碼相關的資料

熱點內容
小米桌面文件夾亂碼怎麼回事 瀏覽:856
點歌台app怎麼連接 瀏覽:318
大學電腦編程學什麼好 瀏覽:348
上哪裡取消應用加密 瀏覽:172
電氣控制與可編程式控制制器pdf 瀏覽:85
cad圖紙不能跨文件夾粘貼 瀏覽:254
學生雲伺服器主機 瀏覽:885
單片機狀態周期 瀏覽:622
lua中的android 瀏覽:443
加密貴還是植發貴 瀏覽:664
陽光壓縮機繼電器 瀏覽:971
修改阿里雲伺服器密碼 瀏覽:817
lk4102加密晶元 瀏覽:588
怎麼更改app店面 瀏覽:489
設備部門如何做好伺服器 瀏覽:849
androido下載 瀏覽:478
神奇高量戰法副圖源碼 瀏覽:830
匯編語言設計凱撒密碼加密器 瀏覽:392
主次梁加密是加在哪裡 瀏覽:664
模板匹配演算法matlab 瀏覽:825