1

在下面的代码中,我只是想计算一个项目在文件中出现的次数。但是,当我打印出键和它们的值时,我得到的计数比实际值多一个。当我初始化total为 0 时,它解决了问题,但我不知道为什么。

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.HashSet;

public class Problem {
   public static void main(String[] arg) {
      HashSet QID = new HashSet();
      HashMap QIDToCorrect = new HashMap();
      try {
         // Open the file that is the first command line parameter
         FileInputStream fstream = new FileInputStream(
               "C:/Users/lol/Downloads/data.csv");

         // Get the object of DataInputStream
         DataInputStream in = new DataInputStream(fstream);
         BufferedReader br = new BufferedReader(new InputStreamReader(in));

         //Read File Line By Line
         String strLine;
         br.readLine(); //skip header line
         int total = 0;
         int blah = 0;
         while ((strLine = br.readLine()) != null) {

            String[] split = strLine.split(",");

            if (!QID.contains(split[0])) {
               total = 1;
               QID.add(split[0]);
               QIDToCorrect.put(split[0], total);
            } else {
               total += 1;
               QIDToCorrect.put(split[0], total);
            }

            //System.out.println();
         }
      } catch (Exception e) {
      }
   }
}
4

3 回答 3

0

假设您输入了每行的第一个元素如下所示:

foo
foo
bar
foo

现在让我们考虑一下你的循环对这个输入做了什么

而 ((strLine = br.readLine()) != null) {

        String[] split = strLine.split(",");

split[0]是第一个“foo”。

        if (!QID.contains(split[0])) {

“foo”尚未添加

           total = 1;
           QID.add(split[0]);
           QIDToCorrect.put(split[0], total);

total设置为1, "foo" 添加到QID和 ("foo", 1) 添加到QIDToCorrect

        String[] split = strLine.split(",");

split[0]是第二个“foo”

        if (!QID.contains(split[0])) {

评估为假,因此if语句落入else.

        } else {
           total += 1;
           QIDToCorrect.put(split[0], total);
        }

total递增到 2 并QIDToCorrect更新为 ("foo", 2)。

        String[] split = strLine.split(",");

split[0]现在包含“栏”。

        if (!QID.contains(split[0])) {
           total = 1;
           QID.add(split[0]);
           QIDToCorrect.put(split[0], total);

QID不包含 bar,因此total重置为 1,将 "bar" 添加到 中QID,并将 ("bar", 1) 插入到QIDToCorrect中。

        String[] split = strLine.split(",");

现在split[0]包含第三个“foo”

        if (!QID.contains(split[0])) {

"foo" 以前见过,所以请转到else.

        } else {
           total += 1;
           QIDToCorrect.put(split[0], total);
        }

total递增到 2 并QIDToCorrect用 ("foo", 2) 更新。

因此,您的包含计数器的地图认为只有两个 foos。我在这里看到一个问题。total每次看到新项目时,您的计数器都会重置。因此,当您打电话时QIDToCorrect.put(),不要考虑您过去看到该项目的次数。您可能需要使用QIDToCorrect.get()才能获得项目的先前计数。这消除了对total变量的需要(除非您想知道您看到的所有项目的总数)。此外,QIDHashSet 是不必要的,因为您可以查询QIDToCorrect它是否已经包含一个键。

于 2013-01-19T00:52:29.017 回答
0

你的算法看起来很奇怪,但如果我正确理解你想要做什么,我会替换

if (!QID.contains(split[0])) {
               total = 1;
               QID.add(split[0]);
               QIDToCorrect.put(split[0], total);
            } else {
               total += 1;
               QIDToCorrect.put(split[0], total);
            }

Integer lasttotal = (Integer)QIDToCorrect.get(split[0]);
total = 1 + lasttotal!=null ? lasttotal : 0;
QID.add(split[0]);
QIDToCorrect.put(split[0], total);

这样,即使它们没有排序,总数也会正确计算您的项目......但是,这并不能解释您的问题。你确定你打印的值正确吗?您是否尝试过逐步调试?

于 2013-01-18T23:23:51.943 回答
0

您需要在更新之前获取密钥的值......见下文:

if (!QID.contains(split[0])) {
   total = 1;
   QID.add(split[0]);
   QIDToCorrect.put(split[0], total);
} else {
   total = QIDToCorrect.get(split[0]);  // RETRIEVE VALUE FOR KEY
   total += 1;
   QIDToCorrect.put(split[0], total);
}
于 2013-01-19T00:34:28.050 回答