为什么HashMap大小与文件中的行数不同?

时间:2012-04-16 00:56:11

标签: java file hashmap

假设我有一个文件,例如具有以下类型的数据:

 info1 word1
 info2 word2
 info3 word3
 info2 word4

现在,我想为每行中的单词创建一个映射函数。所以我最初阅读该行,使用空格拆分它,然后得到这个词。

现在这个词就是价值。我知道所有的话都是不同的和独特的。但是,这些信息可能并不是唯一的。

关于密钥,因为我最感兴趣的是与每个单词相关的信息,我只是为它创建一个基本上就是所有行的字符串。

我知道这些信息可能没有什么不同,但肯定是这些,因为这些词语肯定是不同的。

该文件有40000行,但HashMap的大小为38490。

我不明白这里发生了什么。我的逻辑错了吗?

这是代码:

private static void loadInfo(HashMap<String, String> info, File File){
  try {
    BufferedReader br = new BufferedReader(new FileReader(file));
    String[] dataInLine = new String[2];
    String line = br.readLine();
    int counter = 0;
    while (line != null) {

      lineData = line.split("\\s+");
      info.put(lineData[1], line);
      line = br.readLine();
      counter++;
    }
    System.out.println(counter); //counter shows the correct amount of lines
    System.out.println(info.size()); //this shows less than the amount of lines
  } catch (IOException io) {
  }
}

提前致谢

4 个答案:

答案 0 :(得分:3)

如果你有重复的密钥会发生这种情况; put将覆盖之前的值。

答案 1 :(得分:2)

很可能你的单词列表实际上并不是唯一的。您可以在致电.put()之前进行检查,以确定某个字词是否已存在并报告重复:

while (line != null) {

      lineData = line.split("\\s+");
      final String word = lineData[1];
      final String previous = info.get(word);
      if (previous != null) { 
         System.err.println("Duplicate at count "+line+" of word "+word);
         System.err.println(" original line: "+previous);
         System.err.println("      new line: "+line);
      }
      info.put(word, line);
      line = br.readLine();
      counter++;
     }

答案 2 :(得分:0)

你可能有一些重复的密钥。

检查是否要替换以前的值的简单方法是查看put的返回值:

String last = info.put(lineData[1], line);
if( last != null )
    System.err.println("Warning: replaced value for key "+lineData[1]+", last value was: "+last);

答案 3 :(得分:0)

你可能有重复的密钥,例如示例中的“info2”映射到“word2”和“word4”。

如果您需要具有映射到多个值的键,则需要“多图”。您可以使用类型HashMap<String, Set<String>>创建自己的(每个键映射到一组值)。或者使用预先存在的一个,例如Apache Commons中的那个。

使用您自己的,每次要添加映射时,您需要检查密钥是否存在;如果没有将它映射到空集。然后添加映射,将值放入该键的集合中。

HashMap<String, Set<String>> info;
...
if (!info.contains(lineData[1])) {
    info.put(lineData[1], new HashSet<String>());
}
info.get(lineData[1]).put(line);