使用正则表达式从字符串中删除垃圾字符

Har*_*ngh 5 regex

我想删除除az和AZ之外的字符串中的字符.为此创建了以下功能,它工作正常.

public String stripGarbage(String s) {
 String good = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
 String result = "";
 for (int i = 0; i < s.length(); i++) {
     if (good.indexOf(s.charAt(i)) >= 0) {
             result += s.charAt(i);
      }
   }
 return result;
}
Run Code Online (Sandbox Code Playgroud)

谁能告诉我一个更好的方法来实现同样的目标.可能正则表达式可能是更好的选择.

问候

掠夺

Rob*_*boy 5

干得好:

result = result.replaceAll("[^a-zA-Z0-9]", "");
Run Code Online (Sandbox Code Playgroud)

但是如果你理解你的代码并且它是可读的,那么也许你有最好的解决方案:

有些人在遇到问题时会想“我知道,我会使用正则表达式”。现在他们有两个问题。


Ste*_*n C 4

以下内容应该比使用正则表达式的任何内容以及您的初始尝试更快。

public String stripGarbage(String s) {
    StringBuilder sb = new StringBuilder(s.length());
    for (int i = 0; i < s.length(); i++) {
        char ch = s.charAt(i);
        if ((ch >= 'A' && ch <= 'Z') || 
            (ch >= 'a' && ch <= 'z') ||
            (ch >= '0' && ch <= '9')) {
            sb.append(ch);
        }
    }
    return sb.toString();
}
Run Code Online (Sandbox Code Playgroud)

关键点:

  • 使用 StringBuilder 比循环中的字符串连接要快得多。(后者生成N - 1垃圾字符串并复制N * (N + 1) / 2字符以构建包含字符的字符串N。)

  • 如果您对结果字符串的长度有很好的估计,那么预分配 StringBuilder 来保存该数量的字符是个好主意。(但是,如果您没有一个好的估计,内部重新分配等的成本会分摊到最终字符串O(N)长度N......所以这通常不是一个主要问题。)

  • 平均而言,针对(最多)3 个字符范围搜索测试字符比在 62 个字符的字符串中搜索字符要快得多。

  • switch 语句可能会更快,特别是如果有更多字符范围。但是,在这种情况下,将需要更多行代码来列出所有字母和数字的情况。

  • 如果非垃圾字符与该类的现有谓词Character(例如Character.isLetter(char)等)匹配,您可以使用它们。如果您想匹配任何字母或数字……而不仅仅是 ASCII 字母和数字,这将是一个不错的选择。

  • 需要考虑的其他替代方法是使用 aHashSet<Character>或 aboolean[]按字符索引,这些字符预先填充了非垃圾字符。如果编译时未知非垃圾字符集,这些方法可以很好地工作。