我需要您的帮助,因为我不知道为什么我在哈希图中更新值(针对特定键)会更改几乎所有其他键的值... 您可以尝试以下相应的代码:
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分别包含以下字符串:
我得到:
****** 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]}
我真的不明白为什么在“更新:是[brief1.txt,brief2.txt]”行上,代码为此ArrayList值更新了map的所有键。即使它将更新所有键的值:为什么除了狗以外的所有键?
预先感谢您的帮助!
答案 0 :(得分:3)
这是因为您一直将相同的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
作为值类型。
答案 1 :(得分:2)
您一次创建了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<>());
答案 2 :(得分:2)
1。正确
您放置在地图中的newWord
始终是相同的实例,因此每个键的值都具有相同的list
,您可以对其进行更改并随处可见,因此您需要放置一个新的{每次{1}}:
list
2。改进
不使用原始类型,使用泛型: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
,您可以简化add
部分,然后总是{{1 }}。对于check
部分,您可以使用add
check
方法同时进行检查和放置
3.Shorten
putIfAbsent()
会尝试从密钥中获取值,如果没有该密钥,则将其插入新的Map
。computeIfAbsent
)HashSet
设置为此值,就无需检查,因为我们使用的是HashSet
,并且不可能重复add