亚洲免费在线视频-亚洲啊v-久久免费精品视频-国产精品va-看片地址-成人在线视频网

您的位置:首頁技術文章
文章詳情頁

為什么在foreach循環中JAVA集合不能添加或刪除元素

瀏覽:99日期:2022-08-10 17:45:49
目錄1. 編碼強制規約2. 原因分析3. 相關知識介紹3.1. 什么是快速失敗(fail-fast)?3.2. 什么是安全失敗(fail-safe)呢?1. 編碼強制規約

在《阿里巴巴Java開發手冊》中,針對集合操作,有一項規定,如下:

【強制】不要在 foreach 循環里進行元素的 remove/add 操作。remove 元素請使用 Iterator方式,如果并發操作,需要對 Iterator 對象加鎖。

public class SimpleTest { public static void main(String[] args) {List<String> list = Lists.newArrayList();list.add('1');list.add('2');list.add('3');list.add('4'); //正例Iterator<String> iterator = list.iterator();while (iterator.hasNext()) { String item = iterator.next(); if ('1'.equalsIgnoreCase(item)) {iterator.remove(); }} //反例for (String item : list) { if ('2'.equals(item)) {list.remove(item); }} }}2. 原因分析

在循環或迭代時,會首先創建一個迭代實例,這個迭代實例的expectedModCount 賦值為集合的modCount.

每當迭代器使⽤ hashNext() / next() 遍歷下⼀個元素之前,都會檢測 modCount 變量與expectedModCount 值是否相等,相等的話就返回遍歷;否則就拋出異常【ConcurrentModificationException】,終⽌遍歷

如果在循環中添加或刪除元素,是直接調用集合的add,remove方法【導致了modCount增加或減少】,但這些方法不會修改迭代實例中的expectedModCount,導致在迭代實例中expectedModCount 與 modCount的值不相等,拋出ConcurrentModificationException異常

但迭代器中的remove,add方法,會在調用集合的remove,add方法后,將expectedModCount 重新賦值為modCount,所以在迭代器中增加、刪除元素是可以正常運行的。

可以參考ArrayList中的內部私有類Itr、ListItr的源碼

public Iterator<E> iterator() {return new Itr(); } /** * An optimized version of AbstractList.Itr */ private class Itr implements Iterator<E> {int cursor; // index of next element to returnint lastRet = -1; // index of last element returned; -1 if no suchint expectedModCount = modCount; Itr() {} //刪除了一些代碼 public void remove() { if (lastRet < 0)throw new IllegalStateException(); checkForComodification(); try {ArrayList.this.remove(lastRet);cursor = lastRet;lastRet = -1;expectedModCount = modCount; } catch (IndexOutOfBoundsException ex) {throw new ConcurrentModificationException(); }} final void checkForComodification() { if (modCount != expectedModCount)throw new ConcurrentModificationException();} } public E remove(int index) {rangeCheck(index); modCount++;E oldValue = elementData(index); int numMoved = size - index - 1;if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved);elementData[--size] = null; // clear to let GC do its work return oldValue; }3. 相關知識介紹3.1. 什么是快速失敗(fail-fast)?

快速失敗(fail-fast) 是 Java 集合的⼀種錯誤檢測機制。在使⽤迭代器對集合進⾏遍歷的時候,在多線程下操作⾮安全失敗(fail-safe)的集合類可能就會觸發 fail-fast 機制,導致拋出ConcurrentModificationException 異常。

另外,在單線程下,如果在遍歷過程中對集合對象的內容進⾏了修改的話也會觸發 fail-fast 機制。

舉個例⼦:多線程下,如果線程 1 正在對集合進⾏遍歷,此時線程 2 對集合進⾏修改(增加、刪除、修改),或者線程 1 在遍歷過程中對集合進⾏修改,都會導致線程 1 拋出ConcurrentModificationException 異常。

3.2. 什么是安全失敗(fail-safe)呢?

采⽤安全失敗機制的集合容器,在遍歷時不是直接在集合內容上訪問的,⽽是先復制原有集合內容,在拷⻉的集合上進⾏遍歷。所以,在遍歷過程中對原集合所作的修改并不能被迭代器檢測到,故不會拋ConcurrentModificationException 異常。

到此這篇關于為什么在foreach循環中JAVA集合不能添加或刪除元素的文章就介紹到這了,更多相關JAVA集合添加或刪除元素內容請搜索好吧啦網以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持好吧啦網!

標簽: Java
相關文章:
主站蜘蛛池模板: 亚洲国产精品a一区二区三区 | 毛片a级三毛片免费播放 | 欧美不卡视频在线观看 | 亚洲国产精品影院 | 亚洲国产精品成人久久 | 草草国产成人免费视频 | 国产精品18久久久久网站 | 欧美成人黄色 | 国产精品密蕾丝视频 | 亚洲在线播放 | 日韩欧美国产精品第一页不卡 | 亚欧成人毛片一区二区三区四区 | 亚洲精品日本 | 日韩美女在线视频 | 悟空影视大全免费影视 | 久艹精品 | 欧美一级特黄aa大片视频 | 国产区在线免费观看 | 久久精品视频在线观看 | 亚洲男人的天堂在线 | 一级女人毛片 | 久草资源在线播放 | 久久黄色影片 | 99je全部都是精品视频在线 | 成人黄激情免费视频 | 久久久久88色偷偷免费 | 日韩中文字幕精品 | 欧美日韩国产一区二区三区播放 | 日韩欧美国产成人 | 国内精品免费一区二区观看 | 国产成人精品日本亚洲专一区 | 在线视频日本 | 国产永久免费视频m3u8 | 欧美二级在线观看免费 | 亚洲欧美卡通动漫丝袜美腿 | 国产成人a毛片在线 | 伊人狼人影院 | 久久青草免费免费91线频观看 | 国产或人精品日本亚洲77美色 | 亚洲天堂免费 | 久草精品视频 |