【问题标题】:java.util.ConcurrentModificationException when removing elements from a hashmap从哈希图中删除元素时出现 java.util.ConcurrentModificationException
【发布时间】:2014-10-21 18:56:18
【问题描述】:

我正在学习HashMap 类并编写了这个简单的程序。 此代码适用于将元素添加到 hashmap 并从 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'

代码:

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

更新:工作代码

感谢你们俩(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();
    }
}

【问题讨论】:

标签: java hashmap


【解决方案1】:

在迭代 Map 时,您正在调用 remove。这行,增强的 for 循环,隐式运行 Iterator

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

Iterator 检测到其集合被修改时,它会抛出ConcurrentModificationException。但是,您可以在Iterator 本身上调用remove(),而不会引发该异常。明确使用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.
   }
}

【讨论】:

    【解决方案2】:

    您不能从当前正在迭代的地图中删除元素。您可以定义一个迭代器,或者您可以在案例 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;
    

    【讨论】:

      【解决方案3】:

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

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

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

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

      【讨论】:

      • 我更喜欢使用while(it.hasNext()) 的版本,因为for循环通常用于预先知道迭代次数的循环。好吧,几年前我在大学就被告知了。
      • @Julien:当然,几乎是一样的;唯一的区别是 for 循环将迭代器变量的范围保持在 for 块的本地。
      【解决方案4】:

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

      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
      
      
      }
      

      【讨论】:

        【解决方案5】:

        可以使用 Collections 类的 removeIf。

        map.keySet().removeIf(key -> key.equals("someThing"));
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-12-13
          • 2013-11-09
          • 1970-01-01
          • 1970-01-01
          • 2011-03-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多