Java 嵌套的 For 循环突然中断

Java nested For-loop breaking abruptly

我是一名程序员爱好者,已经学习Java 大约一个月了。因此,我决定解决 r/dailyprogramming 提供的问题。 link 感兴趣的请看下面:

http://www.reddit.com/r/dailyprogrammer/comments/2nynip/2014121_challenge_191_easy_word_counting/

到目前为止,我已经将单词拆分为一个名为 splitted 的字符串数组。这些词都是小写的,句点、逗号和一些其他常见的标点符号,导致数组中充满了小写字母的词。目前我正在尝试通过获取数组的第一个不为空的单词然后检查每个元素并对每次出现进行计数来计算每个单词的出现次数。我使用嵌套的 for 循环和 if 语句来完成此操作。但是,程序会突然停止而不会返回任何错误。我希望有人能向我解释为什么我的代码突然停止。

在这部分代码之前一切正常。

for (int i = 0; i < splitted.length; i++) {

    if (splitted[i] != null) {

        word = splitted[i];
        System.out.println("Word is: " + word);

            for (int j = i; j < splitted.length; j++) {

                if (splitted[j].contains(word)) {

                    splitted[j] = null;
                    count++;
                }
            }

        System.out.println(word + ": " + count);
        count = 0;
    }           
}

这是修改后的代码,在不同的点都有输出。我已经检查了数组长度,它没有超出范围。

for (int i = 0; i < splitted.length; i++) {

    if (splitted[i] != null) {

        word = splitted[i];
        System.out.println("Word is: " + word);

            for (int j = i; j < splitted.length; j++) {

                System.out.printf("%d %s %B%n", j, splitted[j], splitted[j].contains(word));
                if (splitted[j].contains(word)) {

                    splitted[j] = null;
                    count++;
                }

                System.out.println(j + " is less than " + splitted.length);
            }

        System.out.println(word + ": " + count);
        count = 0;
    }
        System.out.println(splitted[i] + " " + i);          
}

为了更清楚而编辑:问题是程序在检查数组中的空元素后突然停止,尽管 j 小于 splitted.length。

输出:

Today was great hello stupid Today. Today was bad. Today was amazing. He is great. He was bad.    Now he is great! 
Word is: today
0 today TRUE
0 is less than 22
1 was FALSE
1 is less than 22
2 great FALSE
2 is less than 22
3 hello FALSE
3 is less than 22
4 stupid FALSE
4 is less than 22
5 today TRUE
5 is less than 22
6 today TRUE
6 is less than 22
7 was FALSE
7 is less than 22
8 bad FALSE
8 is less than 22
9 today TRUE
9 is less than 22
10 was FALSE
10 is less than 22
11 amazing FALSE
11 is less than 22
12 he FALSE
12 is less than 22
13 is FALSE
13 is less than 22
14 great FALSE
14 is less than 22
15 he FALSE
15 is less than 22
16 was FALSE
16 is less than 22
17 bad FALSE
17 is less than 22
18 now FALSE
18 is less than 22
19 he FALSE
19 is less than 22
20 is FALSE
20 is less than 22
21 great FALSE
21 is less than 22
today: 4
null 0
Word is: was
1 was TRUE
1 is less than 22
2 great FALSE
2 is less than 22
3 hello FALSE
3 is less than 22
4 stupid FALSE
4 is less than 22

谢谢,

问题是您没有在第二个 for 循环中检查 null

for (int j = i; j < splitted.length; j++) {
    if (splitted[j].contains(word)) {//what if splitted[j] is null?
        splitted[j] = null;
        count++;
    }
}

如果遇到 null,例如因为较早的迭代已将项目设置为 null,则会得到 NullPointerException.

所以你应该使用:

for (int j = i; j < splitted.length; j++) {
    if (splitted[j] != null && splitted[j].contains(word)) {//what if splitted[j] is null?
        splitted[j] = null;
        count++;
    }
}

然而,这段代码还有其他一些不完全正确的方面:

  • 您可能应该使用 equals 而不是包含,因为 "foobarqux".contains("bar")true
  • 您可以通过在计数前先对值进行排序或使用 HashMap<String,Integer> 来更有效地执行此操作(在 O(n log n) 中)实例。

检查此 jdoodle