在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;
}
如果我使用某种StringBuilder或正则表达式,或者其他什么东西会更快吗?是的,我知道:简介并查看,但我希望有人可以提供他们头脑中的答案,因为这是一项常见任务。
答案 0 :(得分:18)
虽然\\p{Punct}
将指定比问题更广泛的字符,但它确实允许更短的替换表达式:
tmp = tmp.replaceAll("\\p{Punct}+", "");
答案 1 :(得分:12)
这是一个迟到的答案,只是为了好玩。
在这种情况下,我建议瞄准速度的可读性。当然,你可以超级可读,但速度太慢,就像这个超简洁的版本一样:
private static String processWord(String x) {
return x.replaceAll("[][(){},.;!?<>%]", "");
}
这很慢,因为每次调用此方法时,都会编译正则表达式。所以你可以预编译正则表达式。
private static final Pattern UNDESIRABLES = Pattern.compile("[][(){},.;!?<>%]");
private static String processWord(String x) {
return UNDESIRABLES.matcher(x).replaceAll("");
}
对于大多数用途,这应该足够快,假设JVM的正则表达式引擎优化了字符类查找。这是我个人会使用的解决方案。
现在没有分析,我不知道你是否可以通过制作自己的角色(实际代码点)查找表做得更好:
private static final boolean[] CHARS_TO_KEEP = new boolean[];
填写一次,然后迭代,生成结果字符串。我会把代码留给你。 :)
同样,我不会深入研究这种优化。代码变得难以阅读。性能是一个令人担忧的问题吗?还要记住,现代语言是JITted,在升温后它们会表现得更好,所以请使用一个好的分析器。
应该提到的一件事是,原始问题中的示例非常不具备性能,因为您正在创建一大堆临时字符串!除非编译器优化所有这些,否则该特定解决方案将执行最差的操作。
答案 2 :(得分: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.");
如果您发现它们对您的需求变慢,那么这可能比使用正则表达式更好。
但是,如果你有一个很长的,不同的特殊字符列表,它可能会很快乱。在这种情况下,正则表达式更容易处理。
答案 3 :(得分:1)
字符串是不可变的因此不好尝试使用它们非常动态地尝试使用StringBuilder而不是String并使用它的所有精彩方法!它会让你做任何你想做的事情。再加上是的,如果你有想要做的事情,找出它的正则表达式,它会为你做得更好。
答案 4 :(得分:0)
使用String#replaceAll(String regex, String replacement)
作为
tmp = tmp.replaceAll("[,.;!?(){}\\[\\]<>%]", "");
System.out.println(
"f,i.l;t!e?r(e)d {s}t[r]i<n>g%".replaceAll(
"[,.;!?(){}\\[\\]<>%]", "")); // prints "filtered string"
答案 5 :(得分:0)
现在,您的代码将遍历tmp
的所有字符,并将其与您要删除的所有可能的字符进行比较,因此它将使用
number of tmp characters
x number or characters you want to remove
比较。
要优化代码,您可以使用短路OR ||
并执行类似
StringBuilder sb = new StringBuilder();
for (char c : tmp.toCharArray()) {
if (!(c == ',' || c == '.' || c == ';' || c == '!' || c == '?'
|| c == '(' || c == ')' || c == '{' || c == '}' || c == '['
|| c == ']' || c == '<' || c == '>' || c == '%'))
sb.append(c);
}
tmp = sb.toString();
或者像这样
StringBuilder sb = new StringBuilder();
char[] badChars = ",.;!?(){}[]<>%".toCharArray();
outer:
for (char strChar : tmp.toCharArray()) {
for (char badChar : badChars) {
if (badChar == strChar)
continue outer;// we skip `strChar` since it is bad character
}
sb.append(strChar);
}
tmp = sb.toString();
通过这种方式,您将遍历每个tmp
个字符,但如果该字符不是%
,则该字符的比较次数可能会减少(因为如果字符为{{1},它将是最后一次比较程序会在一次比较中得到他的结果。)
如果我没有弄错,这种方法会与character class(.
)一起使用,所以也许可以这样试试
[...]
答案 6 :(得分:-1)
你可以这样做:
tmp.replaceAll("\\W", "");
删除标点符号