簡體   English   中英

迭代Arraylist時的ConcurrentModificationException(不刪除)

[英]ConcurrentModificationException while iterating through Arraylist (not removing)

我目前在迭代ArrayList時遇到問題。 我在這里看過幾篇文章,但似乎沒有解決我的問題。 這是我的代碼:

//restaurants contains a list of all restaurants and i want to filter them
List<Restaurant> newList = new ArrayList<Restaurant>();
List<Restaurant> allRestaurants = new ArrayList<Restaurant>(restaurants);
if (query != null && query.length() > 0 && !query.equals("*")) {
            synchronized (allRestaurants) {
                for (Iterator<Restaurant> it = allRestaurants.iterator(); it
                        .hasNext();) {
                    Restaurant restaurant = it.next();
                    if (restaurant.getCity().contains(query)) {
                        synchronized (newList) {
                            newList.add(restaurant);
                        }
                    } else {
                        newList = allRestaurants;
                    }
                }
            }

這是我修改過的代碼,我在這里讀過幾個想法(同步,使用迭代器而不是for-each-loop)。 我甚至已經同步了整個方法,仍然得到一個例外。

例外情況發生在以下行:

Restaurant restaurant = it.next();

我不明白。 我沒有操縱這一行中的列表。 為什么會發生這種情況,我該如何解決?

else{
    newList = allRestaurants;
}

這幾乎肯定是你的問題。

newList分配給allRestaurants然后添加到newList會導致您的編輯。

這是后newList = allRestaurants任何添加到newList將更新MOD計數allRestaurants ,因此你的錯誤。

在else分支中

else {
   newList = allRestaurants;
}

您將newList設置為allRestaurants 下一個修改newList.add(restaurant); 更改allRestaurants列表。

調用it.next()時會拋出異常,因為迭代器會檢查其源是否已更改。

失敗始於:

newList = allRestaurants;

它指向兩個引用相同列表(即您正在迭代的那個)。 然后,您執行以下操作:

newList.add(restaurant);

修改列表。 ConcurrentModificationException的javadoc:

請注意,此異常並不總是表示某個對象已被另一個線程同時修改。 如果單個線程發出違反對象合同的一系列方法調用,則該對象可能會拋出此異常。 例如,如果線程在使用失敗快速迭代器迭代集合時直接修改集合,則迭代器將拋出此異常。

你的問題出在else子句中。

         newList = allRestaurants;

這就是你獲得例外的原因

您不能更改循環內用於迭代的ArrayList; 這就是ConcurrentModificationException所說的( http://docs.oracle.com/javase/1.4.2/docs/api/java/util/ConcurrentModificationException.html )和newList = allRestaurants; 加上newList.add(restaurant); 確實有可能改變列表allRestaurants

所以你能做的就是

  1. 創建另一個列表
  2. 將項目放在該列表中進行修改
  3. 在循環之后添加/刪除新列表( addAllremoveAll )到舊列表

查看http://www.javacodegeeks.com/2011/05/avoid-concurrentmodificationexception.html了解更多信息。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM