web-dev-qa-db-ja.com

反復中に要素を削除してTreeMapに追加するにはどうすればよいですか?

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

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

しかし、私はJava.util.ConcurrentModificationExceptionIteratorも使用しようとしましたが、同じExceptionを取得しました

9
Mahmoud Hanafy

なぜそれがConcurrentModificationExceptionを引き起こしたのか説明

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

for-各ループは、entrySetmapのイテレータも内部的に作成します。マップを反復処理しているときに、値をマップに再度配置することでマップの構造を変更しました(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);
_
10

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

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を使用することをお勧めします。 ConcurrentHashMap

2
SamDJava

コピーを繰り返し処理すると、問題なく追加/削除できます。

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

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

2
Bohemian

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

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

編集:

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

  1. HashMapのコピーを作成します。したがって、一方を繰り返し、もう一方をMapに変更します。
  2. 要件はMapの要素の追加と削除の両方であるため、これにはListIteratorを使用したいと思います[これは通常のIteratorとは異なります]。
  3. Map1のkeysetを取得し、ArrayList(Collection<? extends E> c)を使用してリストに変換します。
  4. ここで、手順3で作成したListIteratorからListを取得し、ListIteratorとMap2の要素を追加および削除します[追加する必要があることを忘れないでください。ListIteratorとMap2の両方で削除してください]。
1
Lokesh

あなたはそれをすることができないので。

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

0
Ahmad