【问题标题】:java - Generating permutations using Hashmap [duplicate]java - 使用Hashmap生成排列[重复]
【发布时间】:2015-08-27 17:19:28
【问题描述】:

我正在尝试编写一个递归程序,它可以打印从文件中获取的整数列表的所有排列,我正在使用 HashMap 来存储列表,其中键是数字,值是键的次数出现在列表中。代码如下:

import java.util.*;
import java.io.*;

public class perm
{
    public static void permute(HashMap<Integer, Integer> map)
    {
        if(map.isEmpty())
        {
            System.out.println();
        }
        else
        {
            Set<Integer> keys = map.keySet();
            for(int num: keys)
            {
                System.out.print(Integer.toString(num)+",");
                int val = map.get(num) -1;
                if(val == 0)
                {
                    map.remove(num);   
                }
                else
                {
                    map.put(num, val);
                }
                permute(map);
            }
        }
    }
    public static void main(String args []) throws FileNotFoundException
    {
        HashMap <Integer, Integer> map = new HashMap<Integer, Integer>();
        Scanner in = new Scanner(new File(args[0]));
        int num;
        while(in.hasNextInt())
        {
            num = in.nextInt();
            if(map.containsKey(num))
            {
                map.put(num, map.get(num)+1);
            }
            else
            {
                map.put(num,1);
            }
        }
        permute(map);
    }
}

我得到一个并发错误,但我不明白为什么,错误如下:

Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.HashMap$HashIterator.nextNode(HashMap.java:1429)
    at java.util.HashMap$KeyIterator.next(HashMap.java:1453)
    at perm.permute(perm.java:15)
    at perm.permute(perm.java:27)
    at perm.permute(perm.java:27)
    at perm.permute(perm.java:27)
    at perm.main(perm.java:48)

--------基于cmets编辑的代码--------------------

import java.util.*;
import java.io.*;

public class perm
{
    public static void permute(HashMap<Integer, Integer> map)
    {
        if(map.isEmpty())
        {
            System.out.println();
        }
        else
        {
            Iterator it = map.entrySet().iterator(); 
            //Set<Integer> keys = map.keySet();
            while(it.hasNext())
            //for(int num: keys)
            {
                Map.Entry pair = (Map.Entry)it.next();
                int num = (int) pair.getKey();
                System.out.print(Integer.toString(num)+",");
                int val = (int) pair.getValue()-1;
                //HashMap<Integer, Integer> newMap = map;
                //int val = map.get(num) -1;
                if(val == 0)
                {
                    //newMap.remove(num);
                    it.remove(); 
                }
                else
                {
                    //newMap.put(num, val);
                    pair.setValue(val);
                }
                permute(map);
            }
        }
    }
    public static void main(String args []) throws FileNotFoundException
    {
        HashMap <Integer, Integer> map = new HashMap<Integer, Integer>();
        Scanner in = new Scanner(new File(args[0]));
        int num;
        while(in.hasNextInt())
        {
            num = in.nextInt();
            if(map.containsKey(num))
            {
                map.put(num, map.get(num)+1);
            }
            else
            {
                map.put(num,1);
            }
        }
        permute(map);
    }
}

同样的错误仍然存​​在。然后我回到最初的方法并存储了我试图迭代的 HashMap 的临时副本,并且只修改了临时副本而不是原始副本,同样的错误仍然存​​在。

---- 基于答案 1 的代码编辑 ------

import java.util.*;
import java.io.*;

public class perm
{
    public static void permute(HashMap<Integer, Integer> map)
    {
        if(map.isEmpty())
        {
            System.out.println();
        }
        else
        {
            //Iterator it = map.entrySet().iterator(); 
            HashMap<Integer, Integer> newMap = map;
            Set<Integer> keys = map.keySet();
            //while(it.hasNext())
            for(int num: keys)
            {
                //Map.Entry pair = (Map.Entry)it.next();
                //int num = (int) pair.getKey();
                System.out.print(Integer.toString(num)+",");
                //int val = (int) pair.getValue()-1;
                //HashMap<Integer, Integer> newMap = map;
                int val = map.get(num) -1;
                if(val == 0)
                {
                    newMap.remove(num);
                    //it.remove(); 
                }
                else
                {
                    newMap.put(num, val);
                    //pair.setValue(val);
                }
                permute(newMap);
            }
        }
    }
    public static void main(String args []) throws FileNotFoundException
    {
        HashMap <Integer, Integer> map = new HashMap<Integer, Integer>();
        Scanner in = new Scanner(new File(args[0]));
        int num;
        while(in.hasNextInt())
        {
            num = in.nextInt();
            if(map.containsKey(num))
            {
                map.put(num, map.get(num)+1);
            }
            else
            {
                map.put(num,1);
            }
        }
        permute(map);
    }
}

【问题讨论】:

  • 我使用了上述线程中的建议,但仍然遇到同样的错误。
  • 请发布您的更新代码。如果你正确使用了这个帖子的建议,你不会得到ConcurrentModificationException
  • 在---Edit line---之后添加的代码---
  • remove() 上的 it 声明很好。问题是对pair.setValue(...) 的调用。在此表单中迭代此地图时,您无法将元素添加到地图。一般的方法是创建一个新的临时地图,并在迭代后合并这些地图。
  • 对上次编辑的评论:newMapmap 是同一个对象。同样的问题也适用。您可以批量插入/删除并在完成迭代后应用它们吗?

标签: java hashmap


【解决方案1】:

java.util.ConcurrentModificationException 在您修改正在迭代的集合时抛出。在您的情况下,您既要迭代又要修改 HashMap 方法中的 permute

如果没有抛出此异常,那么每次程序运行时,您最终都会得到奇怪且看似随机的结果,具体取决于生成的 hashCode 整数(从映射中添加或删除)。

【讨论】:

  • 更详细地说,禁止并发修改会强制执行迭代可靠性,因为当您迭代一个集合时,您知道它的长度或内容不会改变。您可以创建另一个作为键 List 副本的对象并对其进行迭代,或者记录您要进行的所有插入,然后在迭代后一次完成所有插入。
  • 在上面的程序中,我正在迭代一组键,它是一个独立于 HashMap 的集合。我正在迭代 Set 并修改 HashMap,它们是两个不同的集合,所以我不明白为什么会出现此错误。
  • 当您在 HashMap 中添加或删除条目时,您也在修改该 HashMap(您正在迭代的集合)的键。
【解决方案2】:

您收到 ConcurrentModificationException 是因为您在迭代时尝试修改地图。理解它的好链接 http://javarevisited.blogspot.com/2012/02/fail-safe-vs-fail-fast-iterator-in-java.html

【讨论】:

    猜你喜欢
    • 2011-12-24
    • 1970-01-01
    • 2011-03-07
    • 2014-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-15
    相关资源
    最近更新 更多