代码之家  ›  专栏  ›  技术社区  ›  Martin Carre

Java:为什么我更新哈希表中一个特定的键的数组值会改变所有其他的键值?

  •  0
  • Martin Carre  · 技术社区  · 7 年前

    我需要你的帮助,因为我不知道为什么我更新的哈希图中的一个值(对于一个特定的键)几乎改变了所有其他键的值… 下面是您可以尝试的相应代码:

    import edu.duke.*;
    import java.util.*;
    import java.io.*;
    
    public class WordsInFiles {
        private HashMap<String, ArrayList> map;
    
        public WordsInFiles(){
            map = new HashMap<String, ArrayList>();
        }
    
        private void addWordsFromFile(File f) {
            FileResource fr = new FileResource(f);
            String fileName = f.getName();
            ArrayList<String> newWord = new ArrayList<String>();
            for (String s : fr.words()){
                if (!map.containsKey(s)) {
                    newWord.clear();
                    newWord.add(fileName);
                    map.put(s, newWord);
                    System.out.println("New:" + s + "\t" + newWord);
                } else {
                    ArrayList<String> currArr = map.get(s);
                    if (!currArr.contains(fileName)){
                        currArr.add(fileName);
                        newWord = currArr;
                        System.out.println("Update:" +s + "\t" + newWord);
                        map.put(s, newWord);
                    }
                }
                System.out.println(map + "\n");
            }
        }
    
        public void tester() {
            System.out.println("\n ****** New Tester Instance ****** ");
            buildWordFileMap();
        }
    }
    

    通过在分别包含字符串的4个文件上运行检测仪:brief1.txt、brief2.txt、brief3.txt和brief4.txt:

    1. 猫又有趣又可爱
    2. 狗是愚蠢的
    3. 爱动物猫狗
    4. 爱鸟爱猫

    我得到:

     ****** New Tester Instance ****** 
    New:cats    [brief1.txt]
    {cats=[brief1.txt]}
    
    New:are [brief1.txt]
    {cats=[brief1.txt], are=[brief1.txt]}
    
    New:funny   [brief1.txt]
    {cats=[brief1.txt], are=[brief1.txt], funny=[brief1.txt]}
    
    New:and [brief1.txt]
    {cats=[brief1.txt], are=[brief1.txt], and=[brief1.txt], funny=[brief1.txt]}
    
    New:cute    [brief1.txt]
    {cats=[brief1.txt], are=[brief1.txt], and=[brief1.txt], cute=[brief1.txt], funny=[brief1.txt]}
    
    New:dogs    [brief2.txt]
    {cats=[brief1.txt], are=[brief1.txt], and=[brief1.txt], dogs=[brief2.txt], cute=[brief1.txt], funny=[brief1.txt]}
    
    Update:are  [brief1.txt, brief2.txt]
    {cats=[brief1.txt, brief2.txt], are=[brief1.txt, brief2.txt], and=[brief1.txt, brief2.txt], dogs=[brief2.txt], cute=[brief1.txt, brief2.txt], funny=[brief1.txt, brief2.txt]}
    
    New:silly   [brief2.txt]
    {cats=[brief2.txt], are=[brief2.txt], and=[brief2.txt], silly=[brief2.txt], dogs=[brief2.txt], cute=[brief2.txt], funny=[brief2.txt]}
    
    New:love    [brief3.txt]
    {love=[brief3.txt], cats=[brief2.txt], are=[brief2.txt], and=[brief2.txt], silly=[brief2.txt], dogs=[brief2.txt], cute=[brief2.txt], funny=[brief2.txt]}
    
    New:animals [brief3.txt]
    {love=[brief3.txt], cats=[brief2.txt], are=[brief2.txt], and=[brief2.txt], silly=[brief2.txt], dogs=[brief2.txt], animals=[brief3.txt], cute=[brief2.txt], funny=[brief2.txt]}
    
    Update:cats [brief2.txt, brief3.txt]
    {love=[brief3.txt], cats=[brief2.txt, brief3.txt], are=[brief2.txt, brief3.txt], and=[brief2.txt, brief3.txt], silly=[brief2.txt, brief3.txt], dogs=[brief2.txt], animals=[brief3.txt], cute=[brief2.txt, brief3.txt], funny=[brief2.txt, brief3.txt]}
    
    {love=[brief3.txt], cats=[brief2.txt, brief3.txt], are=[brief2.txt, brief3.txt], and=[brief2.txt, brief3.txt], silly=[brief2.txt, brief3.txt], dogs=[brief2.txt], animals=[brief3.txt], cute=[brief2.txt, brief3.txt], funny=[brief2.txt, brief3.txt]}
    
    Update:dogs [brief2.txt, brief3.txt]
    {love=[brief3.txt], cats=[brief2.txt, brief3.txt], are=[brief2.txt, brief3.txt], and=[brief2.txt, brief3.txt], silly=[brief2.txt, brief3.txt], dogs=[brief2.txt, brief3.txt], animals=[brief3.txt], cute=[brief2.txt, brief3.txt], funny=[brief2.txt, brief3.txt]}
    
    Update:love [brief3.txt, brief4.txt]
    {love=[brief3.txt, brief4.txt], cats=[brief2.txt, brief3.txt], are=[brief2.txt, brief3.txt], and=[brief2.txt, brief3.txt], silly=[brief2.txt, brief3.txt], dogs=[brief2.txt, brief3.txt], animals=[brief3.txt, brief4.txt], cute=[brief2.txt, brief3.txt], funny=[brief2.txt, brief3.txt]}
    
    New:birds   [brief4.txt]
    {love=[brief4.txt], cats=[brief2.txt, brief3.txt], are=[brief2.txt, brief3.txt], and=[brief2.txt, brief3.txt], silly=[brief2.txt, brief3.txt], dogs=[brief2.txt, brief3.txt], animals=[brief4.txt], birds=[brief4.txt], cute=[brief2.txt, brief3.txt], funny=[brief2.txt, brief3.txt]}
    
    Update:and  [brief2.txt, brief3.txt, brief4.txt]
    {love=[brief4.txt], cats=[brief2.txt, brief3.txt, brief4.txt], are=[brief2.txt, brief3.txt, brief4.txt], and=[brief2.txt, brief3.txt, brief4.txt], silly=[brief2.txt, brief3.txt, brief4.txt], dogs=[brief2.txt, brief3.txt], animals=[brief4.txt], birds=[brief4.txt], cute=[brief2.txt, brief3.txt, brief4.txt], funny=[brief2.txt, brief3.txt, brief4.txt]}
    
    {love=[brief4.txt], cats=[brief2.txt, brief3.txt, brief4.txt], are=[brief2.txt, brief3.txt, brief4.txt], and=[brief2.txt, brief3.txt, brief4.txt], silly=[brief2.txt, brief3.txt, brief4.txt], dogs=[brief2.txt, brief3.txt], animals=[brief4.txt], birds=[brief4.txt], cute=[brief2.txt, brief3.txt, brief4.txt], funny=[brief2.txt, brief3.txt, brief4.txt]}
    

    我真的不明白为什么在“update:are[brief1.txt,brief2.txt]”一行中,代码更新了这个arraylist值的所有map键。即使它会更新所有的钥匙的价值:为什么所有的钥匙除了狗?

    提前感谢您的帮助!

    3 回复  |  直到 7 年前
        1
  •  3
  •   Andy Turner    7 年前

    ArrayList

    map.put(s, newWord);
    

    newWord = new ArrayList<>();
    

    newWord

    List<String> newWord = new ArrayList<>();
    newWord.add(fileName);
    map.put(s, newWord);
    

    map.put(s, new ArrayList<>(Arrays.asList(fileName));
    

    Set LinkedHashSet

        2
  •  2
  •   Andy Turner    7 年前

    newWord List map

    ArrayList<String> newWord = new ArrayList<String>(); 
    

    loop

            if (!map.containsKey(s)) {
                newWord.clear();
                newWord.add(fileName);
                map.put(s, newWord); // your problem lies here
                // created just once but put in many times;
                System.out.println("New:" + s + "\t" + newWord);
            } 
    

    map.put(s, new ArrayList<>());
    
        3
  •  2
  •   azro    7 年前

    newWord list

    for (String s : fr.words()){
        if (!map.containsKey(s)) {
            ArrayList<String> newWord = new ArrayList<>();         
            newWord.add(fileName);
            map.put(s, newWord);
        } else {
            ArrayList<String> currArr = map.get(s);
            if (!currArr.contains(fileName)){
                currArr.add(fileName);                            
            }
        }
    }
    

    • HashMap<String, ArrayList<String>> map = new HashMap<>

    • Set List filename add

    • if check & add else check putIfAbsent() Map


    1. computeIfAbsent HashSet
    // map is now a HashMap<String, Set<String>>
    for (String s : fr.words()){
        map.computeIfAbsent(s, k -> new HashSet<>()).add(filename);
    }