我是Java的新手。我以为我会编写一个程序来计算句子中字符或字符序列的出现次数。我写了以下代码。但我后来看到Apache Commons中有一些现成的选项。
无论如何,你能看看我的代码并说出是否有任何菜鸟错误?我测试了几个案例,它工作正常。我可以想到一种情况,如果输入是一个大文本文件而不是一个小句子/段落,split()
函数可能最终会有问题,因为它必须处理一个大变量。然而,这是我的猜测,并希望得到你的意见。
private static void countCharInString() {
//Get the sentence and the search keyword
System.out.println("Enter a sentence\n");
Scanner in = new Scanner(System.in);
String inputSentence = in.nextLine();
System.out.println("\nEnter the character to search for\n");
String checkChar = in.nextLine();
in.close();
//Count the number of occurrences
String[] splitSentence = inputSentence.split(checkChar);
int countChar = splitSentence.length - 1;
System.out.println("\nThe character/sequence of characters '" + checkChar + "' appear(s) '" + countChar + "' time(s).");
}
谢谢:)
答案 0 :(得分:1)
我可以立即想到的一个缺陷是,如果inputSentence
仅由checkChar
一次出现。在这种情况下,split()
将返回一个空数组,您的计数将为-1而不是1。
示例互动:
Enter a sentence
onlyme
Enter the character to search for
onlyme
The character/sequence of characters 'onlyme' appear(s) '-1' time(s).
更好的方法是使用.indexOf()
的{{1}}方法来计算这样的事件:
String
答案 1 :(得分:1)
由于边缘情况,split()
是错误的方法。
相反,请使用replaceAll()
删除所有其他字符,然后使用剩下的length()
来计算点数:
int count = input.replaceAll(".*?(" + check + "|$)", "$1").length() / check.length();
仅供参考,创建的正则表达式(例如check = 'xyz'
时)看起来像".*?(xyz|$)"
,这意味着"所有内容包括' xyz'或输入结束",并被捕获的文本替换(如果输入结束,则为“' xyz'或者没有任何内容”)。这只留下一串0-n复制的检查字符串。然后除以检查的长度给出总数。
为防止检查为空或零长度(导致被零除错误),请严格按照以下方式编码:
int count = check == null || check.isEmpty() ? 0 : input.replaceAll(".*?(" + check + "|$)", "$1").length() / check.length();
答案 2 :(得分:0)
split
是错误的方法:
String.split
采用正则表达式
String.split
针对单个字符进行了优化。如果不是这种情况,那么每次都会创建并编译正则表达式。不过,每次调用它时,String.split
都会为String[]
创建一个对象,并为其中的每个String
创建一个对象。你对这些物品毫无用处;所有你想知道的是伯爵。虽然未来无所不知的HotSpot编译器可能能够对其进行优化,但当前的编译器却没有 - 它大约是简单计算字符数的10倍。checkChar
更好的方法更简单:只需计算字符串中与checkChar
匹配的字符数。如果你考虑采取计算字符所需的步骤,那就是你自己最终得到的结果:
public static int occurrences(String str, char checkChar) {
int count = 0;
for (int i = 0, l = str.length(); i < l; i++) {
if (str.charAt(i) == checkChar)
count++;
}
return count;
}
如果你想计算多个字符的出现次数,那么写一些效率就会变得有点棘手,因为你不想每次都创建一个新的子字符串。
public static int occurrences(String str, String checkChars) {
int count = 0;
int offset = 0;
while ((offset = str.indexOf(checkChars, offset)) != -1) {
offset += checkChars.length();
count++;
}
return count;
}
匹配双字符串的速度仍然是String.split()
警告:效果时间是根据许多情况决定的大概数字。由于差异是一个数量级,因此String.split
一般来说速度较慢是安全的。 (在jdk 1.8.0-b28 64位上进行测试,使用1000万次迭代,在相同的JVM实例中执行10次测试后,验证结果是稳定的,有和没有-Xcomp
相同。)