递归期间的全局变量

时间:2015-01-09 19:22:42

标签: java recursion hashmap anagram


我有一个全局变量masterList,它是一个HashMap。

private static HashMap<ArrayList<String>, Integer> masterList = 
     new HashMap<ArrayList<String>, Integer>();

我有一个递归函数generateAnagram,它将此字符串中的字符串列表放在此HashMap中,并将列表中的字数作为值。但是,HashMap在第一次调用后开始变得混乱,之前的ArrayLists被我试图添加的新的Arraylists覆盖,但之前的值仍然存在。这导致两个键具有相同的值。 这是结果的屏幕截图 - 点击[此处] http://tinypic.com/r/ka1gli/8

    private static void generateAnagram(Set<String> subsets, ArrayList<String> currList, letterMap wordMap) {
            if (wordMap.count() == 0) {
                System.out.println("Adding: " + currList);
                masterList.put(currList, currList.size());
                System.out.println("Current Master: " + masterList.toString());
            } else {
                for (String word : subsets) {
                    if (word.length() <= wordMap.count() && wordMap.isConstructionPossible(word)) {
                        //System.out.println("Word: " + word + "    "  + wordMap.isConstructionPossible(word));
                        wordMap.remove(word);
                        currList.add(word);
                        generateAnagram(subsets, currList, wordMap);
                        currList.remove(word);
                        wordMap.addBack(word);
                    }
                }
            }
}

3 个答案:

答案 0 :(得分:2)

使用ArrayList作为HashMap的关键字并不是一个好主意。每次更改ArrayList的内容(通过添加或删除元素)时,其hashCode都会发生变化,即使它已经在HashMapget()和{ {1}}找不到它,containsKey()会再次添加。

您只有put()的一个实例,您在ArrayList地图中保留put,因此如果您没有更改,地图中只有一个条目该列表的内容一直都在。

答案 1 :(得分:1)

您需要从参数的角度来看这个。 ArrayList引用每次都作为参数传递给您的递归调用,但它仍然指向相同的ArrayList。然后,当您将其放入散列映射中时,您将存储多个对同一个原始ArrayList的引用。

因此在将其添加到主列表之前使用ArrayList.clone()。更好的是,存储一个不可变的集合,以确保你的哈希不会在HashMap中搞砸:

HashMap<List<String>, Integer> masterList = 
      new HashMap<List<String>, Integer>();
...

ArrayList<String> tmp = (ArrayList<String>)currList.clone();
List<String> imm = Collections.unmodifiableList(tmp);
masterList.put(imm, imm.size());

答案 2 :(得分:0)

  

&#34;之前的ArrayLists被我试图添加的新的ArrayLists覆盖,但之前的值仍然存在。&#34;

如果您不想使用以前的值,则可能需要执行类似

的操作

在场景之前:

        final ArrayList<Integer> arrayList = new ArrayList<Integer>();
        final HashMap<ArrayList<Integer>, Integer> hashmap = new HashMap<ArrayList<Integer>, Integer>();

        arrayList.add(1);
        hashmap.put(arrayList, 1);

        arrayList.add(2);
        hashmap.put(arrayList, 1);
        System.out.println(hashmap);

输出:{[1,2] = 1,[1,2] = 1}

情景后:

ArrayList<Integer> arrayList = new ArrayList<Integer>();
final HashMap<ArrayList<Integer>, Integer> hashmap = new HashMap<ArrayList<Integer>, Integer>();

arrayList.add(1);
hashmap.put(arrayList, 1);

arrayList = new ArrayList<Integer>();
arrayList.add(2);
hashmap.put(arrayList, 1);

System.out.println(hashmap);

输出:{[1] = 1,[2] = 1}