【问题标题】:Global variable during recursion递归期间的全局变量
【发布时间】:2015-03-08 04:40:52
【问题描述】:

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

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

我有一个递归函数 generateAnagram,它将 ArrayLists 的字谜放在这个 HashMap 中,并将列表中的单词数作为值。但是,HashMap 在第一次调用后开始混乱,并且以前的 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);
                    }
                }
            }
}

【问题讨论】:

  • 为什么在递归时不使用新的arrayList?如果我没记错的话,我猜你正面临这个问题,因为 arrayList 覆盖了相同的内存位置,这导致了问题

标签: java recursion hashmap anagram


【解决方案1】:

使用ArrayList 作为HashMap 的键不是一个好主意。每次更改ArrayList 的内容(通过添加或删除元素),它的hashCode 都会改变,所以即使它已经在HashMapget()containsKey() 中也找不到它, put() 会再次添加。

您只有一个ArrayList 实例,您将putting 保留在masterList 映射中,因此如果您不更改该列表的所有内容,您的映射中将只有一个条目时间。

【讨论】:

    【解决方案2】:

    你需要从参数的角度来看这个。 ArrayList 引用每次都作为参数传递给您的递归调用,但它仍然指向相同的ArrayList。然后,当您将其放入 hashmap 时,您将存储对相同的单个原始 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());
    

    【讨论】:

      【解决方案3】:

      “以前的 ArrayLists 被我尝试添加的新数组覆盖,但以前的值仍然存在。”

      如果你不想要以前的值,你可能需要做这样的事情

      场景之前:

              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}

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-11-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-04-09
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多