可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
This question already has an answer here:
-
Iterating through a Collection, avoiding ConcurrentModificationException when removing objects in a loop
23 answers
I was doing:
for (Object key : map.keySet())
if (something)
map.remove(key);
which threw a ConcurrentModificationException, so i changed it to:
for (Object key : new ArrayList<Object>(map.keySet()))
if (something)
map.remove(key);
this, and any other procedures that modify the map are in synchronized blocks.
is there a better solution?
if no one comes up with a better solution, first to say no gets the tick ;)
回答1:
As of Java 1.8 you could do this using with:
map.entrySet().removeIf(e-> <boolean expression> );
回答2:
Here is a code sample to use the iterator in a for loop to remove the entry.
Map<String, String> map = new HashMap<String, String>() {
{
put(\"test\", \"test123\");
put(\"test2\", \"test456\");
}
};
for(Iterator<Map.Entry<String, String>> it = map.entrySet().iterator(); it.hasNext(); ) {
Map.Entry<String, String> entry = it.next();
if(entry.getKey().equals(\"test\")) {
it.remove();
}
}
回答3:
Use a real iterator.
Iterator<Object> it = map.keySet().iterator();
while (it.hasNext())
{
it.next();
if (something)
it.remove();
}
Actually, you might need to iterate over the entrySet()
instead of the keySet()
to make that work.
回答4:
is there a better solution?
Well, there is, definitely, a better way to do so in a single statement, but that depends on the condition based on which elements are removed.
For eg: remove all those elements where value
is test, then use below:
map.values().removeAll(Collections.singleton(\"test\"));
UPDATE
It can be done in a single line using Lambda expression in Java 8.
map.entrySet().removeIf(e-> <boolean expression> );
I know this question is way too old, but there isn\'t any harm in updating the better way to do the things :)
回答5:
ConcurrentHashMap
You can use java.util.concurrent.ConcurrentHashMap
.
It implements ConcurrentMap
(which extends the Map
interface).
E.g.:
Map<Object, Content> map = new ConcurrentHashMap<Object, Content>();
for (Object key : map.keySet()) {
if (something) {
map.remove(key);
}
}
This approach leaves your code untouched. Only the map
type differs.
回答6:
Java 8 support a more declarative approach to iteration, in that we specify the result we want rather than how to compute it. Benefits of the new approach are that it can be more readable, less error prone.
public static void mapRemove() {
Map<Integer, String> map = new HashMap<Integer, String>() {
{
put(1, \"one\");
put(2, \"two\");
put(3, \"three\");
}
};
map.forEach( (key, value) -> {
System.out.println( \"Key: \" + key + \"\\t\" + \" Value: \" + value );
});
map.keySet().removeIf(e->(e>2)); // <-- remove here
System.out.println(\"After removing element\");
map.forEach( (key, value) -> {
System.out.println( \"Key: \" + key + \"\\t\" + \" Value: \" + value );
});
}
And result is as follows:
Key: 1 Value: one
Key: 2 Value: two
Key: 3 Value: three
After removing element
Key: 1 Value: one
Key: 2 Value: two
回答7:
You have to use Iterator
to safely remove element while traversing a map.
回答8:
I agree with Paul Tomblin. I usually use the keyset\'s iterator, and then base my condition off the value for that key:
Iterator<Integer> it = map.keySet().iterator();
while(it.hasNext()) {
Integer key = it.next();
Object val = map.get(key);
if (val.shouldBeRemoved()) {
it.remove();
}
}
回答9:
An alternative, more verbose way
List<SomeObject> toRemove = new ArrayList<SomeObject>();
for (SomeObject key: map.keySet()) {
if (something) {
toRemove.add(key);
}
}
for (SomeObject key: toRemove) {
map.remove(key);
}
回答10:
Maybe you can iterate over the map looking for the keys to remove and storing them in a separate collection. Then remove the collection of keys from the map. Modifying the map while iterating is usually frowned upon. This idea may be suspect if the map is very large.
回答11:
And this should work as well..
ConcurrentMap<Integer, String> running = ... create and populate map
Set<Entry<Integer, String>> set = running.entrySet();
for (Entry<Integer, String> entry : set)
{
if (entry.getKey()>600000)
{
set.remove(entry);
}
}
回答12:
Set s=map.entrySet();
Iterator iter = s.iterator();
while (iter.hasNext()) {
Map.Entry entry =(Map.Entry)iter.next();
if(\"value you need to remove\".equals(entry.getKey())) {
map.remove();
}
}