9

私はこのようなコードを書きたい -

for (Map.Entry<Long, Integer> e : map.entrySet()){
    map.remove(k);
    map.put(x, value);
}

しかし、私はjava.util.ConcurrentModificationException 私も使用しようとしましIteratorたが、私は同じを得ましたException

4

6 に答える 6

11

原因の説明ConcurrentModificationException

map.remove(k);
map.put(x, value);

entrySetfor-each ループも内部的にofのイテレータを作成しますmap。マップを繰り返し処理しているときに、値をマップ ( map.put(x,value)) に再度配置してマップの構造を変更したため、これが発生しましConcurrentModificationExceptionた。

ドキュメントでも十分に説明されています-

このクラスのすべての「コレクション ビュー メソッド」によって返される反復子はフェイルファストです。反復子の作成後に、反復子自身の remove メソッド以外の方法でマップが構造的に変更された場合、反復子は ConcurrentModificationException をスローします。 . したがって、同時変更に直面した場合、反復子は、将来の不確定な時点で恣意的で非決定論的な動作を危険にさらすのではなく、迅速かつ明確に失敗します。

これを解決する方法-

反復中にこのマップの構造を変更する必要があります。後でこの値を挿入できます。たとえば、一時的なマップを保持し、反復が仕事を終えたらこれをメイン マップに追加します。

Map<Long, Integer> tempMap = new HashMap<>();
for (Map.Entry<Long, Integer> e : map.entrySet()){
    map.remove(k);
    tempMap.put(x, value);
}
map.putAll(tempMap);
于 2013-05-19T17:10:18.817 に答える
4

コピーを反復すると、問題なく追加/削除できます。

for (Map.Entry<Long, Integer> e : new LinkedHashMap<Long, Integer>(map).entrySet()){
    map.remove(k);
    map.put(x, value);
}

コピーはコピー コンストラクターを介してインラインで作成されるため、これ以上のコード行は必要ありません。LinkedHashMap反復順序を維持するために選択されました(それが重要な場合)。

于 2013-05-20T04:39:05.083 に答える
2

マップから要素を削除するためのサンプル コード スニペットを以下に示します。

for(Iterator<Map.Entry<Long, Integer>> it = map.entrySet().iterator();it.next();)
{
  Map.Entry<String, String> entry = it.next();
 if(//some logic)    
 it.remove();
}

コードに多くの追加と削除が含まれる場合は、ConcurrentHashMap を使用することをお勧めします。コンカレントハッシュマップ

于 2014-09-15T18:12:23.563 に答える
1

コピー コンストラクターを使用してマップのコピーを作成する必要があります。1 を繰り返し、2 番目のマップを変更します。あまり意味がないので、新しく追加された価値を繰り返す必要はないと思います。

コピーを作成することでタスクを達成できます。これは、キーが両方で同じままであるためです。

編集:

新しく追加された要素をハッシュマップに反復するのは良い考えだとは思いません。Iterator が提供する API を確認すると、remove メソッドのみが見つかり、そこには add メソッドはありません。これには理由があり、これについては javadoc を確認できます。ここで、新しく追加された要素を反復する方法について説明します。

  1. のコピーを作成しますHashMap。したがって、一方を繰り返し、もう一方を変更しMapます。
  2. の要素を追加および削除する必要があるため、これMapに使用したいと思いますListIterator[これは通常とは異なりますIterator]。
  3. keysetMap1の を取得し、を使用してリストに変換しArrayList(Collection<? extends E> c)ます。
  4. ここで、ステップ 3 で作成されたものを取得ListIteratorし、Map2 と同様に要素を追加、削除します [Map2と Map2 の両方で追加、削除する必要があることを思い出してください]。ListListIteratorListIterator
于 2013-05-19T16:56:22.537 に答える
0

それはできないからです。

簡単な解決策は、必要な値を配置する別の一時マップを使用し、最終的に元のポインターにポインターを切り替えることです (つまり、 Map = newMap )

于 2013-05-19T17:03:29.277 に答える
0

次のようにマップをたどってみてください

while (tree_map.size() > 0){
     // if k is key
     if (tree_map.containsKey()){
        tree_map.remove(k);
     }
     tree_map.put(x, value);
     break;
     // can go through the for loop or other code as per requirements
 }
于 2022-01-30T10:36:45.437 に答える