Javaの「foreach」を使用してリストから削除することは、通常、大きな禁止事項であり、iterator.remove()を使用する必要があることを知っています。しかし、HashMapのkeySet()をループしている場合は、remove()を使用しても安全ですか?このような:
for(String key : map.keySet()) {
Node n = map.get(key).optimize();
if(n == null) {
map.remove(key);
} else {
map.put(key, n);
}
}
編集:
あなたが実際にマップにaddingしていないことに気づいていませんでした-エントリ内の値を変更しただけです。この場合、pstanton's(pre-edit1)ソリューションはほぼ正しいですが、_map.put
_を呼び出すのではなく、イテレータが返したエントリでsetValue
を呼び出す必要があります。 (それはpossible _map.put
_が機能することを保証しますが、保証されているとは信じていません。ドキュメントでは_entry.setValue
_ willが機能すると述べています。)
_for (Iterator<Map.Entry<String, Node>> it = map.entrySet().iterator();
it.hasNext();)
{
Map.Entry<String, Node> entry = it.next();
Node n = entry.getValue().optimize();
if(n == null)
{
it.remove();
}
else
{
entry.setValue(n);
}
}
_
(entry
にremove
メソッドがないのは残念です。それ以外の場合は、拡張されたforループ構文を使用して、多少扱いにくくすることができます。)
古い答え
(これは、任意の変更を加えたいというより一般的なケースのためにここに残しました。)
いいえ。マップに追加したり、マップから直接削除したりしないでください。 HashSet.keySet()
によって返されるセットは、スナップショットではなく、キーのビューです。
canイテレータを介して削除しますが、拡張forループではなく明示的にイテレータを使用する必要があります。
簡単なオプションの1つは、元のセットから新しいセットを作成することです。
_for (String key : new HashSet<String>(map.keySet())) {
...
}
_
この時点では問題ありません。セットに変更を加えていないからです。
編集:はい、キーセットイテレータを使用して要素を確実に削除できます。 HashMap.keySet()
のドキュメントから:
セットは、Iterator.remove、Set.remove、removeAll、retainAll、およびclearオペレーションを介して、対応するマッピングをマップから削除する要素の削除をサポートしています。 addまたはaddAll操作はサポートしていません。
これはMap
インターフェース自体の中でさえ指定されています。
1 私は、psantonについてコメントするだけでなく、私の回答を編集することにしました。類似しているが明確な状況で得られる追加情報は、この回答を維持するのに十分役立つと考えたためです。
エントリセットを使用する必要があります。
for(Iterator<Map.Entry<String, Node>> it = map.entrySet().iterator(); it.hasNext();)
{
Map.Entry<String, Node> entry = it.next();
Node n = entry.getValue().optimize();
if(n == null)
it.remove();
else
entry.setValue(n);
}
固定コードの編集