天天看點

解決疊代删除導緻的并發修改異常觀察以下代碼是否會發生問題原因是什麼呢?

在程式設計過程中我們經常使用ArrayList,有些時候我們需要删除集合中的元素,這時候有可能你的代碼就會給你點異常。

觀察以下代碼是否會發生問題

List<String> arrayList1 = new ArrayList<String>();
 arrayList1.add("1");
 arrayList1.add("2");
 for (String s : arrayList1) {
     if("1".equals(s)){
         arrayList1.remove(s);
     }
 }
 List<String> arrayList2 = new ArrayList<String>();
 arrayList2.add("2");
 arrayList2.add("1");
 for (String s : arrayList2) {
     if("1".equals(s)){
         arrayList2.remove(s);
     }
 }
           
程式運作結果: arrayList1的remove方法成功執行,但是arrayList2的remove方法運作抛出ConcurrentModificationException異常。

原因是什麼呢?

因為foreach的本質就是使用的疊代器Iterator,所有的Collection集合類都會實作Iterable接口。

找到ArrayList類的iterator()方法

解決疊代删除導緻的并發修改異常觀察以下代碼是否會發生問題原因是什麼呢?

疊代器的本質是先調用hasNext()方法判斷存不存在下一個元素,然後再使用next()方法取下一個元素

解決疊代删除導緻的并發修改異常觀察以下代碼是否會發生問題原因是什麼呢?
上面arraylist1為什麼能remove成功呢,其實它隻循環了一次,是以成功了。

因為它在remove元素1之後,它的size - 1變成1,然後Itr内部的cursor變量由0變成1

此時1 = 1,循環結束,是以成功了。

arraylist2為什麼remove失敗呢,因為他在循環第二次的時候,也remove成功了,但是第三次判斷next的時候cursor的值為2導緻不等于現在的size 1,是以執行了next方法,最重要的來了,之前remove的操作導緻ArrayList的modCount值加1,然後Itr類中的expectedModCount保持不變,是以會抛出異常。
解決疊代删除導緻的并發修改異常觀察以下代碼是否會發生問題原因是什麼呢?
同理可得,由于add操作也會導緻modCount自增,是以不允許在foreach中删除、增加、修改ArrayList中的元素。
推薦大家使用疊代器Iterator删除元素
Iterator<String> iterator = arrayList2.iterator();
 while(iterator.hasNext()){
     String item = iterator.next();
     if("1".equals(item)){
         iterator.remove();
     }
 }
           
如果存在并發操作,還需要對Iterator進行加鎖操作。