Java HashMap即使键存在也返回null值

3
我正在处理一个项目,其中我们向Map中插入键值对。
如果该键存在于Map中,我的代码将返回该键的值。
然而,尽管该键存在,但HashMap并未返回预期的值。
首先,我从文件中读取键和值对,然后我读取另一个文件,该文件几乎具有与第一个文件相同的键。
然后,我为一些键返回值,但对于许多键,其值为null。
以下是我的代码片段:
Scanner scanner = new Scanner(new FileReader("a.txt"));

LinkedHashMap<String, String> map = new LinkedHashMap<String, String>();

while (scanner.hasNextLine())
{
   String[] columns = scanner.nextLine().split(";");
   map.put(columns[0], columns[1]);
}

System.out.println(map);

for (Map.Entry<String, String> entry : map.entrySet())
{ // name is the input of second file
    if (entry.getKey().equals(name)) 
    {
        num = entry.getValue();         
        fun(num);
    }
}

我的输入文件是:
abc;1
def;2
ghi;3
...
并且名称将会是:
abc
def

你能展示一下你的文本文件是什么样子吗? - Rohit Jain
1
为什么要用for循环,当map.get(name)能胜任工作? - kiheru
3
我怀疑可能存在一些尾随或前导空格。 - Rohit Jain
通过使用 map.get(name),它也返回 null 值。 - user2490712
请将 System.out.printf("@%s@\n", name) 放在循环外面,将 System.out.printf("@%s@\n", entry.getKey()) 放在循环内部,并更新问题的输出? @ 表示空格。 - Miserable Variable
那就继续使用 map.get(name)。我非常怀疑使用它会导致任何错误,这些错误在迭代条目集时也不会出现。 - Dennis Meng
2个回答

4

需要比较的字符串可能包含空格、换行符和新行字符。

正如我们之前怀疑的那样,您的输入文件train.txt有许多尾部空格,这导致了地图查询失败。此外,您的Java代码中还有许多冗余的代码块。我已经对其进行了清理。以下是您修改后的代码:

import java.io.*;
import java.util.*;
public class ExampleClass1 {
    public static void main(String[] args) throws IOException {
        Scanner scanner = new Scanner(new FileReader("trainnames.txt"));
        LinkedHashMap<String, String> map = new LinkedHashMap<String, String>();
        while (scanner.hasNextLine()) {
            String[] columns = scanner.nextLine().split(";");
            map.put(columns[0].trim(), columns[1].trim());
        }
        scanner.close();
        System.out.println("******** map is: " + map);
        File file = new File("onn.csv"); // output file
        FileWriter fileWriter = new FileWriter(file);
        scanner = new Scanner(new FileReader("train.txt"));
        while (scanner.hasNextLine()) {
            String line = scanner.nextLine().trim();
            if (line.charAt(0) == '>') {
                //System.out.println("==== line: [" + line + ']');      
                String num = map.get(line);
                no(num, fileWriter);
            }
        }
        scanner.close();
        fileWriter.close();
    }

    public static void no(String num, FileWriter fileWriter) throws IOException {
        fileWriter.append(num + ',' + System.getProperty("line.separator"));
        System.out.println(num);                                        
    }
}

\W 包含的字符不仅仅是空格。而 replaceAll 将会移除所有这些字符,而不仅仅是在两端的字符。 - Rohit Jain
4
你可以使用 name.trim() 来去除字符串两端的空格。 - Rohit Jain
是的,您绝对可以这样做,仅从两端删除空格。 - anubhava
展示 System.out.println(map);System.out.println('[' + name + ']'); 的输出。 - anubhava
对于某些键,它打印出来的是值,而对于另一些键,则返回null。 - user2490712
显示剩余9条评论

3

如果插入对象后hashCode发生变化,则可能会出现此问题。

如果您正在修改作为HashMap键使用的对象,则有两个选项:

  1. 使用IdentityHashMap替换HashMap。这可能会产生意想不到的后果,因为具有相同hashCode的两个对象在从地图中放置/获取时将不再被视为等效,包括完全克隆。
  2. 在以更改hashCode的方式更新键之前,从映射中删除其,然后更新键,最后重新插入映射中。

你如何处理这个问题? - Dylan
@Dylan 我添加了一些备选方案。 - Charlie

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接