最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java HashMap 如何正確遍歷并刪除元素的方法小結

 更新時間:2019年05月30日 09:13:17   作者:zhangnf  
這篇文章主要介紹了Java HashMap 如何正確遍歷并刪除元素的方法小結,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

(一)HashMap的遍歷

HashMap的遍歷主要有兩種方式:

第一種采用的是foreach模式,適用于不需要修改HashMap內元素的遍歷,只需要獲取元素的鍵/值的情況。

HashMap<K, V> myHashMap;
for (Map.entry<K, V> item : myHashMap.entrySet()){
  K key = item.getKey();
  V val = item.getValue();
  //todo with key and val
  //WARNING: DO NOT CHANGE key AND val IF YOU WANT TO REMOVE ITEMS LATER
}

第二種采用迭代器遍歷,不僅適用于HashMap,對其它類型的容器同樣適用。

采用這種方法的遍歷,可以用下文提及的方式安全地對HashMap內的元素進行修改,并不會對后續(xù)的刪除操作造成影響。

for (Iterator<Map.entry<K, V>> it = myHashMap.entrySet().iterator; it.hasNext();){
  Map.Entry<K, V> item = it.next();
  K key = item.getKey();
  V val = item.getValue();
  //todo with key and val
  //you may remove this item using "it.remove();"
}

(二)HashMap之刪除元素

如果采用第一種的遍歷方法刪除HashMap中的元素,Java很有可能會在運行時拋出異常。

HashMap<String, Integer> myHashMap = new HashMap<>();
myHashMap.put("1", 1);
myHashMap.put("2", 2);
for (Map.Entry<String, Integer> item : myHashMap.entrySet()){
  myHashMap.remove(item.getKey());
}
for (Map.Entry<String, Integer> item : myHashMap.entrySet()){
  System.out.println(item.getKey());

運行上面的代碼,Java拋出了 java.util.ConcurrentModificationException 的異常。并附有如下信息。

at java.util.HashMap$HashIterator.nextNode(Unknown Source)
at java.util.HashMap$EntryIterator.next(Unknown Source)
at java.util.HashMap$EntryIterator.next(Unknown Source)

可以推測,由于我們在遍歷HashMap的元素過程中刪除了當前所在元素,下一個待訪問的元素的指針也由此丟失了。

所以,我們改用第二種遍歷方式。

代碼如下:

for (Iterator<Map.Entry<String, Integer>> it = myHashMap.entrySet().iterator(); it.hasNext();){
  Map.Entry<String, Integer> item = it.next();
  //... todo with item
  it.remove();
}
for (Map.Entry<String, Integer> item : myHashMap.entrySet()){
  System.out.println(item.getKey());
}

運行結果沒有顯示,表明HashMap中的元素被正確刪除了。

(三)在HashMap的遍歷中刪除元素的特殊情況

上述方法可能足以應付多數(shù)的情況,但是如果你的HashMap中的鍵值同樣是一個HashMap,假設你需要處理的是 HashMap<HashMap<String, Integer>, Double> myHashMap 時,很不碰巧,你可能需要修改myHashMap中的一個項的鍵值HashMap中的某些元素,之后再將其刪除。

  這時,單單依靠迭代器的 remove() 方法是不足以將該元素刪除的。

  例子如下:

HashMap<HashMap<String, Integer>, Integer> myHashMap = new HashMap<>();
HashMap<String, Integer> temp = new HashMap<>();
temp.put("1", 1);
temp.put("2", 2);
myHashMap.put(temp, 3);
for (Iterator<Map.Entry<HashMap<String, Integer>, Integer>> 
  it = myHashMap.entrySet().iterator(); it.hasNext();){
  Map.Entry<HashMap<String, Integer>, Integer> item = it.next();
  item.getKey().remove("1");
  System.out.println(myHashMap.size());
  it.remove();
  System.out.println(myHashMap.size());
}

結果如下:

1
1

雖然 it.remove(); 被執(zhí)行,但是并沒有真正刪除元素。

原因在于期望刪除的元素的鍵值(即 HashMap<String, Integer> temp )被修改過了。

解決方案:

既然在這種情況下,HashMap中被修改過的元素不能被刪除,那么不妨直接把待修改的元素直接刪除,再將原本所需要的“修改過”的元素加入HashMap。

想法很好,代碼如下:

for (Iterator<Map.Entry<HashMap<String, Integer>, Integer>> 
  it = myHashMap.entrySet().iterator(); it.hasNext();){
  Map.Entry<HashMap<String, Integer>, Integer> item = it.next();
  //item.getKey().remove("1");
  HashMap<String, Integer> to_put = new HashMap<>(item.getKey());
  to_put.remove("1");
  myHashMap.put(to_put, item.getValue());
  System.out.println(myHashMap.size());
  it.remove();
  System.out.println(myHashMap.size());
}

但是依然是RE:

Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.HashMap$HashIterator.remove(Unknown Source)

原因在于,迭代器遍歷時,每一次調用 next() 函數(shù),至多只能對容器修改一次。上面的代碼則進行了兩次修改:一次添加,一次刪除。

既然 java.util.ConcurrentModificationException 異常被拋出了,那么去想辦法拿掉這個異常即可。

最后的最后,我決定棄HashMap轉投ConcurrentHashMap。將myHashMap定義為ConcurrentHashMap之后,其它代碼不動。

運行結果如下:

2
1

最終,通過ConcurrentHashMap和一些小技巧的使用,變形實現(xiàn)了對被修改過鍵值的元素的刪除。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關文章

  • Java源碼解析阻塞隊列ArrayBlockingQueue常用方法

    Java源碼解析阻塞隊列ArrayBlockingQueue常用方法

    今天小編就為大家分享一篇關于Java源碼解析阻塞隊列ArrayBlockingQueue常用方法,小編覺得內容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-01-01
  • JVM堆外內存源碼完全解讀分析

    JVM堆外內存源碼完全解讀分析

    這篇文章主要為大家介紹了JVM堆外內存的核心原理的源碼解讀的完全分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助祝大家多多進步,早日升職加薪
    2022-01-01
  • 淺談Java內存區(qū)域劃分和內存分配策略

    淺談Java內存區(qū)域劃分和內存分配策略

    這篇文章主要介紹了淺談Java內存區(qū)域劃分和內存分配策略,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-05-05
  • java Servlet 實現(xiàn)動態(tài)驗證碼圖片示例

    java Servlet 實現(xiàn)動態(tài)驗證碼圖片示例

    這篇文章主要介紹了java Servlet 實現(xiàn)動態(tài)驗證碼圖片示例的資料,這里整理了詳細的代碼,有需要的小伙伴可以參考下。
    2017-02-02
  • Java數(shù)據(jù)結構(線性表)詳解

    Java數(shù)據(jù)結構(線性表)詳解

    本文主要介紹了Java數(shù)據(jù)結構(線性表)的相關知識。具有很好的參考價值,下面跟著小編一起來看下吧
    2017-01-01
  • mybatisPlus填坑之邏輯刪除的實現(xiàn)

    mybatisPlus填坑之邏輯刪除的實現(xiàn)

    本文主要介紹了mybatisPlus填坑之邏輯刪除的實現(xiàn),文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • java 引用類型的數(shù)據(jù)傳遞的是內存地址實例

    java 引用類型的數(shù)據(jù)傳遞的是內存地址實例

    這篇文章主要介紹了java 引用類型的數(shù)據(jù)傳遞的是內存地址實例,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-10-10
  • Java中Scanner用法實例解析

    Java中Scanner用法實例解析

    Scanner?指的是java.util包下的Scanner類,可以接收控制臺輸入的數(shù)據(jù),下面這篇文章主要給大家介紹了關于Java中Scanner用法實例的相關資料,文中通過實例代碼以及圖文介紹的非常詳細,需要的朋友可以參考下
    2022-11-11
  • SpringBoot整合weixin-java-pay實現(xiàn)微信小程序支付的示例代碼

    SpringBoot整合weixin-java-pay實現(xiàn)微信小程序支付的示例代碼

    微信小程序支付是常見的一種功能,本文主要介紹了SpringBoot整合weixin-java-pay實現(xiàn)微信小程序支付的示例代碼,文中通過示例代碼介紹的非常詳細,需要的朋友們下面隨著小編來一起學習學習吧
    2024-05-05
  • SpringBoot項目中application.yml和bootstrap.yml文件的區(qū)別及說明

    SpringBoot項目中application.yml和bootstrap.yml文件的區(qū)別及說明

    `application.yml`和`bootstrap.yml`都是Spring Boot項目中的配置文件,但它們在加載時機、用途、優(yōu)先級、配置來源、適用場景和是否必須存在等方面存在區(qū)別
    2025-03-03

最新評論

大渡口区| 石狮市| 潜江市| 保德县| 宜宾县| 五原县| 田林县| 于田县| 开原市| 厦门市| 新和县| 昌平区| 平阳县| 新兴县| 吉木萨尔县| 松原市| 榆社县| 北京市| 遂昌县| 闽清县| 太仆寺旗| 慈利县| 衡南县| 荔浦县| 临江市| 丹凤县| 汕尾市| 益阳市| 平定县| 奎屯市| 桐梓县| 蕲春县| 沾化县| 呼玛县| 临桂县| 新晃| 金阳县| 定远县| 徐州市| 海丰县| 渭源县|