java—迭代并从Map中删除

rlcwz9us  于 2021-07-03  发布在  Java
关注(0)|答案(12)|浏览(332)

这个问题在这里已经有答案了

遍历集合,在移除循环中的对象时避免concurrentmodificationexception(27个答案)
三年前关门了。
我在做:

for (Object key : map.keySet())
    if (something)
        map.remove(key);

引发了concurrentmodificationexception,所以我将其更改为:

for (Object key : new ArrayList<Object>(map.keySet()))
    if (something)
        map.remove(key);

此过程以及修改Map的任何其他过程都在同步块中。
有更好的解决办法吗?
如果没有人能想出更好的解决办法,首先说“不”会让你感到高兴;)

wj8zmpe1

wj8zmpe11#

使用真正的迭代器。

Iterator<Object> it = map.keySet().iterator();

while (it.hasNext())
{
  it.next();
  if (something)
    it.remove();
 }

实际上,您可能需要在 entrySet() 而不是 keySet() 为了让它工作。

ukqbszuj

ukqbszuj2#

concurrenthashmap
你可以用 java.util.concurrent.ConcurrentHashMap .
它实现了 ConcurrentMap (扩展了 Map 接口)。
例如。:

Map<Object, Content> map = new ConcurrentHashMap<Object, Content>();

for (Object key : map.keySet()) {
    if (something) {
        map.remove(key);
    }
}

这种方法使代码保持不变。只有 map 类型不同。

pxyaymoc

pxyaymoc3#

有更好的解决办法吗?
当然,在一个语句中有更好的方法,但这取决于基于哪些元素被移除的条件。
例如:去掉那些 value 是测试,则使用以下方法:

map.values().removeAll(Collections.singleton("test"));

在Java8中,可以使用lambda表达式在一行中更新它。

map.entrySet().removeIf(e-> <boolean expression> );

我知道这个问题太老了,但是更新更好的方法并没有什么坏处:)

1szpjjfi

1szpjjfi4#

你必须使用 Iterator 在遍历Map时安全地删除元素。

vsmadaxz

vsmadaxz5#

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();
    }
}
cnjp1d6j

cnjp1d6j6#

我同意保罗汤姆布林的观点。我通常使用键集的迭代器,然后根据该键的值设置条件:

Iterator<Integer> it = map.keySet().iterator();
while(it.hasNext()) {
    Integer key = it.next();
    Object val = map.get(key);
    if (val.shouldBeRemoved()) {
        it.remove();
    }
}
q5lcpyga

q5lcpyga7#

这也应该管用。。

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.getKey());    
  }
}
pokxtpni

pokxtpni8#

也许您可以在Map上迭代,寻找要删除的键,并将它们存储在一个单独的集合中。然后从Map中删除密钥集合。通常不赞成在迭代时修改Map。如果Map很大,这个想法可能会受到怀疑。

5hcedyr0

5hcedyr09#

Java8支持更具声明性的迭代方法,因为我们指定了我们想要的结果,而不是如何计算它。新方法的好处是可读性更强,不易出错。

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 ); 
    });
}

结果如下:

Key: 1   Value: one
Key: 2   Value: two
Key: 3   Value: three
After removing element
Key: 1   Value: one
Key: 2   Value: two
z2acfund

z2acfund10#

对于java 8,您可以按以下方式执行:

map.entrySet().removeIf(e -> <boolean expression>);

oracle文档: entrySet() 集合由Map支持,因此对Map的更改将反映在集合中,反之亦然

qzwqbdag

qzwqbdag11#

另一种更冗长的方式

List<SomeObject> toRemove = new ArrayList<SomeObject>();
for (SomeObject key: map.keySet()) {
    if (something) {
        toRemove.add(key);
    }
}

for (SomeObject key: toRemove) {
    map.remove(key);
}
mbskvtky

mbskvtky12#

下面是一个代码示例,用于在for循环中使用迭代器删除条目。

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();
    }
}

相关问题