日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java中集合删除元素时候关于ConcurrentModificationException的迷惑点

發布時間:2025/7/25 java 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java中集合删除元素时候关于ConcurrentModificationException的迷惑点 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

下面的示例來至于阿里巴巴Java開發手冊的集合處理部分的第7條:

運行如下代碼,會發現正確運行。

public static void hasNotExcption() {List<String> list1 = new ArrayList<String>();list1.add("1");list1.add("2");for (String item : list1) {System.out.println("item : "+item);if ("1".equals(item)) {list1.remove(item);}}}

但是運行如下代碼,則異常:java.util.ConcurrentModificationException(和1中的代碼區別是上面移除判斷條件是1,下面的判斷條件是2)

public static void hasExcption() {List<String> list1 = new ArrayList<String>();list1.add("1");list1.add("2");for (String item : list1) {System.out.println("item : "+item);if ("2".equals(item)) { list1.remove(item);}}}

?

再看如下代碼示例,運行結果見注釋:

/***沒有異常*/public static void hasNotExcption() {List<String> list1 = new ArrayList<String>();list1.add("1");list1.add("2");list1.add("3");list1.add("4");for (String item : list1) {System.out.println("item : " + item);// 移除1和3時候會拋ConcurrentModificationException異常// 但是移除2的時候不會拋出異常if ("3".equals(item)) {list1.remove(item);}}}/*** 有異常*/public static void hasExcption1() {List<String> list1 = new ArrayList<String>();list1.add("1");list1.add("2");list1.add("3");for (String item : list1) {// 增強的for循環底層實現使用的是迭代器if ("1".equals(item)) {// 移除并修改“modCount變量”,導致下次遍歷時候異常 list1.remove(item);}}}/*** 有異常*/public static void hasExcption2() {List<String> list1 = new ArrayList<String>();list1.add("1");list1.add("2");list1.add("3");for (String item : list1) {if ("3".equals(item)) {list1.remove(item);}}}

通過上面三個例子是不是發現了結論?只要移除的是倒數第二個元素的話,就不會發生異常!的確是,移除倒數第二個元素的話就不會異常,那究竟是為什么呢?

?

知識點1:關于增強for循環的實現

集合的增強for循環實現內部使用的是迭代器,可以通過eclipse的F5調試跟蹤。

List<String> list1 = new ArrayList<String>();list1.add("1");list1.add("2");list1.add("3");for (String item : list1) {if ("3".equals(item)) {list1.remove(item);}}

?

知識點2:集合如果判定的是并發修改錯誤?

細心的話可以通過異常發現異常的判斷代碼是:

if (modCount != expectedModCount)throw new ConcurrentModificationException();

其中的modCount是記錄集合的修改次數,而expectedModCount是記錄的預期的修改次數,當集合的修改次數和預期修改次數不一致的時候則發生異常。

那么什么時候會修改modCount呢?當我們對集合進行刪除或者添加元素時候此時記錄集合的修改次數就會發生增加,但是期望的修改次數不會變化,當檢查判斷異常條件時候就會根據條件處理。

?

到此回歸到上面問題,對于hasExcption1和hasExcption2是如何發生異常的?本例對hasExcption1進行詳細解釋:

/*** 有異常*/public static void hasExcption1() {List<String> list1 = new ArrayList<String>();list1.add("1");list1.add("2");list1.add("3");// 增強的for循環底層實現使用的是迭代器。所以每一次都是調用一個hasNext,然后在調用next方法返回元素給itemfor (String item : list1) {if ("1".equals(item)) {// 移除并修改“modCount變量”,導致下次遍歷時候異常 list1.remove(item);}}}

增強的for循環底層實現使用的是迭代器。所以每一次都是調用一個hasNext,然后在調用next方法返回元素給item。當我們刪除元素之后,下一次循環時候會先調用hasNext是否還有元素,此時還有。在調用next方法返回該元素給item,但是調用next方法時候會檢測

集合修改次數和預期修改次數是否相等,如果不等的話則拋出異常。(本例是不等的,因為移除1之后modCount=4,而expectModCount=3)。

?

那么為什么刪除倒數第二個元素不會異常呢?示例代碼:

/***沒有異常*/public static void hasNotExcption() {List<String> list1 = new ArrayList<String>();list1.add("1");list1.add("2");list1.add("3");list1.add("4");for (String item : list1) {if ("3".equals(item)) {list1.remove(item);}}}

因為我們刪除倒數第二個元素時候,此時size=size-1,當刪除完元素進入下一次循環時候,此時hasNext方法判斷是否還有元素的時候返回是false(hasNext使用的是游標和size進行比較)。所以就不會調用next方法了。上面例子我們知道異常就是在next方法中拋的,所以

刪除倒數第二個元素就不會有異常。

?

注意:如果刪除的是倒數第二個元素那么最后的結果是否正確呢?答案:顯然是不正確的。

通過如下示例代碼檢驗:

/***沒有異常*/public static void hasNotExcption() {List<String> list1 = new ArrayList<String>();list1.add("1");list1.add("2");list1.add("3");list1.add("3");for (String item : list1) {if ("3".equals(item)) {list1.remove(item);}}// 顯然最后一個3沒有刪除,所以結果錯誤System.out.println(list1); //[1, 2, 3] }

結果是錯誤的,原因:因為最后一個元素由于在移除倒數第二個元素時候將size-1了,所以遍歷集合提前結束了。所以沒有完全移除掉所有的“3”

?

轉載于:https://www.cnblogs.com/leodaxin/p/7651630.html

總結

以上是生活随笔為你收集整理的Java中集合删除元素时候关于ConcurrentModificationException的迷惑点的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。