从哈希图中删除元素时出现 java.util.ConcurrentModificationException

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26494197/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 10:01:27  来源:igfitidea点击:

java.util.ConcurrentModificationException when removing elements from a hashmap

javahashmap

提问by cyberpirate92

I am learning about HashMapclass and wrote this simple program. this code works good for adding elements to the hashmap and while removing elements from the hashmap , I am encountering java.util.ConcurrentModificationExceptionfor example here is a copy of my terminal,

我正在学习HashMap课程并编写了这个简单的程序。这段代码适用于向哈希图中添加元素,并在从哈希图中删除元素时,我遇到java.util.ConcurrentModificationException例如这里是我的终端的副本,

[ravi@doom test]$ java TestHashMap 
.....MENU.....
1. Add
2. remove key
3. remove value
4. display
7. Exit
Your choice :1

 Key : A

 Value : 1
Key/Value : (A,1) added to storage.
.....MENU.....
1. Add
2. remove key
3. remove value
4. display
7. Exit
Your choice :1

 Key : B

 Value : 2
Key/Value : (B,2) added to storage.
.....MENU.....
1. Add
2. remove key
3. remove value
4. display
7. Exit
Your choice :1

 Key : C

 Value : 3
Key/Value : (C,3) added to storage.
.....MENU.....
1. Add
2. remove key
3. remove value
4. display
7. Exit
Your choice :1

 Key : D

 Value : 4
Key/Value : (D,4) added to storage.
.....MENU.....
1. Add
2. remove key
3. remove value
4. display
7. Exit
Your choice :4
( D , 4 );
( A , 1 );
( B , 2 );
( C , 3 );
.....MENU.....
1. Add
2. remove key
3. remove value
4. display
7. Exit
Your choice :2
Key to REMOVE : 
D
Pair (D,4) Removed.
.....MENU.....
1. Add
2. remove key
3. remove value
4. display
7. Exit
Your choice :4
( A , 1 );
( B , 2 );
( C , 3 );
.....MENU.....
1. Add
2. remove key
3. remove value
4. display
7. Exit
Your choice :3
Enter Value to remove : 2
Key : B Removed.
Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.HashMap$HashIterator.nextEntry(HashMap.java:922)
    at java.util.HashMap$EntryIterator.next(HashMap.java:962)
    at java.util.HashMap$EntryIterator.next(HashMap.java:960)
    at TestHashMap.start(TestHashMap.java:60)
    at TestHashMap.main(TestHashMap.java:87)
ABRT problem creation: 'success'

code:

代码:

import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

class TestHashMap
{
    private Map<String,Integer> map;
    public TestHashMap()
    {
        map = new HashMap<String,Integer>();
    }
    public void displayMenu()
    {
        System.out.println(".....MENU.....");
        System.out.println("1. Add");
        System.out.println("2. remove key");
        System.out.println("3. remove value");
        System.out.println("4. display");
        System.out.println("7. Exit");
        System.out.print("Your choice :");
    }
    public void start()
    {
        Scanner input = new Scanner(System.in);
        int menuChoice,value;
        String key;
        while(true)
        {
            displayMenu();
            menuChoice = input.nextInt();
            switch(menuChoice)
            {
                case 1:
                    System.out.print("\n Key : ");
                    input.nextLine();
                    key = input.nextLine();
                    System.out.print("\n Value : ");
                    value = input.nextInt();
                    map.put(key,new Integer(value));
                    System.out.println("Key/Value : ("+key+","+value+") added to storage.");
                break;
                case 2:
                    System.out.println("Key to REMOVE : ");
                    input.nextLine();
                    key = input.nextLine();
                    Integer v = map.get(key);
                    if(v == null)
                        System.out.println("No value exists for key "+key);
                    else
                    {
                        map.remove(key);
                        System.out.println("Pair ("+key+","+v.intValue()+") Removed.");
                    }
                    break;
                case 3:
                    System.out.print("Enter Value to remove : ");
                    value = input.nextInt();
                    if(map.containsValue(new Integer(value)))
                    {
                        for(Map.Entry<String,Integer> entry : map.entrySet() )
                        {
                            if(entry.getValue().intValue() == value)
                            {
                                System.out.println("Key : "+entry.getKey()+" Removed.");
                                map.remove(entry.getKey());
                            }
                        }
                    }
                break;
                case 4:
                    for(Map.Entry<String,Integer> entry : map.entrySet() )
                    {
                        System.out.println("( "+entry.getKey()+" , "+entry.getValue()+" );");
                    }
                break;
                case 7:
                    input.close();
                    System.exit(0);
                default:
                    System.out.println("Invalid Choice !");
            }
        }
    }
    public static void main(String args[])
    {
        TestHashMap thm = new TestHashMap();
        thm.start();
    }
}

UPDATE: working code

更新:工作代码

thanks to both (rgettman,Nathan Hughes) of you.

感谢你们(rgettmanNathan Hughes)。

import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
import java.util.Iterator;

class TestHashMap
{
    private Map<String,Integer> map;
    public TestHashMap()
    {
        map = new HashMap<String,Integer>();
    }
    public void displayMenu()
    {
        System.out.println(".....MENU.....");
        System.out.println("1. Add");
        System.out.println("2. remove key");
        System.out.println("3. remove value");
        System.out.println("4. display");
        System.out.println("7. Exit");
        System.out.print("Your choice :");
    }
    public void start()
    {
        Scanner input = new Scanner(System.in);
        int menuChoice,value;
        String key;
        while(true)
        {
            displayMenu();
            menuChoice = input.nextInt();
            switch(menuChoice)
            {
                case 1:
                    System.out.print("\n Key : ");
                    input.nextLine();
                    key = input.nextLine();
                    System.out.print("\n Value : ");
                    value = input.nextInt();
                    map.put(key,new Integer(value));
                    System.out.println("Key/Value : ("+key+","+value+") added to storage.");
                break;
                case 2:
                    System.out.println("Key to REMOVE : ");
                    input.nextLine();
                    key = input.nextLine();
                    Integer v = map.get(key);
                    if(v == null)
                        System.out.println("No value exists for key "+key);
                    else
                    {
                        map.remove(key);
                        System.out.println("Pair ("+key+","+v.intValue()+") Removed.");
                    }
                    break;
                case 3:
                    System.out.print("Enter Value to remove : ");
                    value = input.nextInt();
                    if(map.containsValue(new Integer(value)))
                    {
                        for (Iterator<Map.Entry<String, Integer>> it = map.entrySet().iterator();it.hasNext();) 
                        {
                            Map.Entry<String,Integer> x = it.next();
                            if(x.getValue().intValue() == value)
                            {
                                key = x.getKey();
                                it.remove();
                                System.out.println("Key : "+key+" Removed.");
                            }
                        }
                    }
                break;
                case 4:
                    for(Map.Entry<String,Integer> entry : map.entrySet() )
                    {
                        System.out.println("( "+entry.getKey()+" , "+entry.getValue()+" );");
                    }
                break;
                case 7:
                    input.close();
                    System.exit(0);
                default:
                    System.out.println("Invalid Choice !");
            }
        }
    }
    public static void main(String args[])
    {
        TestHashMap thm = new TestHashMap();
        thm.start();
    }
}

回答by Nathan Hughes

Your for-loop gets the map.entrySet and uses the iterator on it to work through the map entries (this version of the for-loop requires an Iterable, it gets the iterator from the Iterable). When you are using an iterator on a map, but remove things from the map without using that iterator, you get the ConcurrentModificationException. That is the map telling the iterator that it's out of date.

您的 for 循环获取 map.entrySet 并使用其上的迭代器来处理映射条目(此版本的 for 循环需要一个 Iterable,它从 Iterable 获取迭代器)。当您在地图上使用迭代器,但在不使用该迭代器的情况下从地图中删除内容时,您会得到 ConcurrentModificationException。那就是告诉迭代器它已经过时的映射。

You can write a for loop using the iterator explicitly, like this:

您可以显式使用迭代器编写 for 循环,如下所示:

for (Iterator<Map.Entry<String, Integer> it = map.entrySet().iterator();
it.hasNext();) {

and use the iterator's remove method when you need to delete an entry.

并在需要删除条目时使用迭代器的 remove 方法。

回答by rgettman

You are calling removewhile you're iterating over the Map. This line, the enhanced for loop, runs an Iteratorimplicitly:

remove在迭代Map. 这一行,增强的 for 循环,Iterator隐式运行:

for(Map.Entry<String,Integer> entry : map.entrySet() )

When an Iteratordetects that its collection is modified, it throws a ConcurrentModificationException. However, you can call remove()on the Iteratoritself without that exception being thrown. Use an Iteratorexplicitly:

Iterator检测到它的集合被修改时,它会抛出一个ConcurrentModificationException. 但是,您可以remove()Iterator不抛出异常的情况下调用它本身。Iterator明确使用:

Iterator<Map.Entry<String, Integer>> itr = map.entrySet().iterator();
while(itr.hasNext())
{
   Map.Entry<String, Integer> entry = itr.next();
   if(entry.getValue().intValue() == 2)
   {
      System.out.println("Key : "+entry.getKey()+" Removed.");
      itr.remove();  // Call Iterator's remove method.
   }
}

回答by IdusOrtus

You cannot remove an element from a map which you are currently iterating over. You could define an iterator, or you could make a few simple modifications to your code within the block for case 3.

您无法从当前正在迭代的地图中删除元素。您可以定义一个迭代器,或者您可以对案例 3 的块中的代码进行一些简单的修改。

case 3:
    System.out.print("Enter Value to remove : ");
    value = input.nextInt();
    if(map.containsValue(new Integer(value)))
    {
        Map.Entry<String,Integer> foo = null;
        for(Map.Entry<String,Integer> entry : map.entrySet() )
            if(entry.getValue().intValue() == value)
                foo = entry;

        System.out.println("Key : "+foo.getKey()+" Removed.");
        map.remove(foo.getKey());
    }
    break;

回答by Keshav bansal

Just Use Iterator class to remove the Iterating Element as

只需使用 Iterator 类将迭代元素删除为

for (Iterator<Map.Entry<String, Integer> it = map.entrySet().iterator();
while(it.hasNext()) {
  Map.Entry<String, Integer> e= itr.next();
  key = e.getKey();
  Value = e.getValue();

  //Your Other Code Here

   it.remove();                    //It removes the current Itertaion from Map


}