从Java中的字符串中有效删除特定字符(一些标点符号)?

VPe*_*ric 6 java regex string

在Java中,从String中删除给定字符的最有效方法是什么?目前,我有这个代码:

private static String processWord(String x) {
    String tmp;

    tmp = x.toLowerCase();
    tmp = tmp.replace(",", "");
    tmp = tmp.replace(".", "");
    tmp = tmp.replace(";", "");
    tmp = tmp.replace("!", "");
    tmp = tmp.replace("?", "");
    tmp = tmp.replace("(", "");
    tmp = tmp.replace(")", "");
    tmp = tmp.replace("{", "");
    tmp = tmp.replace("}", "");
    tmp = tmp.replace("[", "");
    tmp = tmp.replace("]", "");
    tmp = tmp.replace("<", "");
    tmp = tmp.replace(">", "");
    tmp = tmp.replace("%", "");

    return tmp;
}
Run Code Online (Sandbox Code Playgroud)

如果我使用某种StringBuilder,或正则表达式,或者其他东西,会更快吗?是的,我知道:简介并查看,但我希望有人可以提供他们头脑的答案,因为这是一项常见的任务.

Rei*_*eus 18

虽然\\p{Punct}会指定比问题更广泛的字符,但它确实允许更短的替换表达式:

tmp = tmp.replaceAll("\\p{Punct}+", "");
Run Code Online (Sandbox Code Playgroud)

  • 您是否认为'\\ p {Punct}'的实施效率高于仅指定[.,!<> {}](以及其他)作为角色类? (2认同)

Ray*_*oal 12

这是一个迟到的答案,只是为了好玩.

在这种情况下,我建议瞄准速度的可读性.当然,你可以超级可读但速度太慢,就像这个超简洁版本一样:

private static String processWord(String x) {
    return x.replaceAll("[][(){},.;!?<>%]", "");
}
Run Code Online (Sandbox Code Playgroud)

这很慢,因为每次调用此方法时,都会编译正则表达式.所以你可以预编译正则表达式.

private static final Pattern UNDESIRABLES = Pattern.compile("[][(){},.;!?<>%]");

private static String processWord(String x) {
    return UNDESIRABLES.matcher(x).replaceAll("");
}
Run Code Online (Sandbox Code Playgroud)

假设JVM的正则表达式引擎优化了字符类查找,这对于大多数用途来说应该足够快.这是我个人使用的解决方案.

现在没有分析,我不知道你是否可以通过制作自己的角色(实际代码点)查找表做得更好:

private static final boolean[] CHARS_TO_KEEP = new boolean[];
Run Code Online (Sandbox Code Playgroud)

填写一次,然后迭代,生成结果字符串.我会把代码留给你.:)

同样,我不会深入研究这种优化.代码变得难以阅读.性能是一个令人担忧的问题吗?还要记住,现代语言是JITted,在升温后它们会表现得更好,所以使用一个好的分析器.

应该提到的一件事是,原始问题中的示例非常不具有性能,因为您正在创建一大堆临时字符串!除非编译器优化所有这些,否则该特定解决方案将执行最差.

  • 这不是真的:正则表达式,"[] [(){} ,.;!?<>%]",无效,因为它包含特殊字符.但是,使用\ Q和\ E引用效果很好:""[\\ Q] [(){} ,.;!?<>%\\ E]"(由于Java,反斜杠加倍).我将接受这个答案,因为它是我最终使用的,所有替代品都清楚地解释了;更不用说只有提到的确切字符被这个删除了. (6认同)

Tom*_*lak 5

你可以这样做:

static String RemovePunct(String input) 
{
    char[] output = new char[input.length()];
    int i = 0;

    for (char ch : input.toCharArray())
    {
        if (Character.isLetterOrDigit(ch) || Character.isWhitespace(ch)) 
        {
            output[i++] = ch;
        }        
    }

    return new String(output, 0, i);
}

// ...

String s = RemovePunct("This is (a) test string.");
Run Code Online (Sandbox Code Playgroud)

如果您发现它们对您的需求变慢,那么这可能比使用正则表达式更好.

但是,如果你想删除一个很长的,特殊的特殊字符列表,它可能会变得很乱.在这种情况下,正则表达式更容易处理.

http://ideone.com/mS8Irl