使用string.split()计算Java中字符串的出现次数

时间:2014-03-30 00:55:47

标签: java regex string

我是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).");
}

谢谢:)

3 个答案:

答案 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()

的10-12倍

警告:效果时间是根据许多情况决定的大概数字。由于差异是一个数量级,因此String.split一般来说速度较慢是安全的。 (在jdk 1.8.0-b28 64位上进行测试,使用1000万次迭代,在相同的JVM实例中执行10次测试后,验证结果是稳定的,有和没有-Xcomp相同。)