替换/前置字符串中的字符集

时间:2011-03-14 08:05:50

标签: java guava

我想替换一些字符集,并且为了这个目的使用了CharMatcher的番石榴,现在我需要增强一个方法 - 现在我需要替换一些字符,就像' %' - > '!%',我不知道如何用番石榴这样做,所以在阅读this question后,我使用了正则表达式。和代码类似 -

s.replaceAll("['\\\\]", "\\\\$0");

但它是同一方法的一部分,并且在相同的字符串操作方法中使用CharMather和regex看起来不太一致,所以我只是想知道我是否也可以将CharMatcher用于此目的。
我没有测试正则表达式方法是否比CharMatcher更快,反之亦然,但如果CharMatcher可以处理这个问题,那么我们想知道如何知道哪种方法更有效。

4 个答案:

答案 0 :(得分:2)

好吧,我想我明白你想做什么。

Guava的CharMatcher不允许您在替换CharSequence中引用匹配的字符(“反向引用”)。

例如,如果要将“i”替换为“!i”,将“j”替换为“!j”,则不能执行:

String string = ...;
CharMatcher.anyOf("ij").replaceFrom(string, "!$0");

你必须这样做:

String string = ...;
string = CharMatcher.is('i').replaceFrom(string, "!i");
string = CharMatcher.is('j').replaceFrom(string, "!j");

这很烦人,因为代码更脏(代码更多),性能更差(字符串字符将被多次迭代)。

如果你发现自己经常这样做,我想你可以创建一个实用工具方法,灵感来自CharMatcher.replaceFrom(),当一个字符与给定的CharMatcher匹配时,它会预先设置一个String:

public static String prepend(CharSequence sequence, CharMatcher charMatcher, CharSequence toPrepend) {
    if (toPrepend.length() == 0) {
        return sequence.toString();
    }

    String string = sequence.toString();
    int pos = charMatcher.indexIn(string);
    if (pos == -1) {
        return string;
    }

    int len = string.length();
    StringBuilder buf = new StringBuilder((len * 3 / 2) + 16);

    int oldpos = 0;
    do {
        buf.append(string, oldpos, pos);
        buf.append(toPrepend);
        buf.append(string.charAt(pos));
        oldpos = pos + 1;
        pos = charMatcher.indexIn(string, oldpos);
    } while (pos != -1);

    buf.append(string, oldpos, len);
    return buf.toString();
}

并像这样使用它:

MyCharMatchers.prepend(string, CharMatcher.anyOf("aei"), "!");

我不知道性能影响。我认为CharMatcher比正则表达式更快,但你必须benchmark才能确定它。

答案 1 :(得分:2)

如果我是你,我不会只关心CharMatcher。事实上我并不关心只使用Guava,但我关心Guava试图强制执行的优秀设计。

如果番石榴无法帮助您,请使用您可以使用的产品。这不是因为我们使用Guava,我们无权查看其他组件。如果正则表达式是您所需要的并且Guava没有提供合适的替代品,那么您有充分的理由继续使用正则表达式。

显然,您可能希望将其封装在特定的方法/类中,以使其可以重复使用。我所关心的只是代码足够可读和高效。

例如,不要使用String#replaceAll(),而是编译j.u.regex.Pattern并重复使用该模式并使用Pattern#matcher()Matcher#replaceAll(String)

示例:

public class Regexes {
  public static Function<String,String> replaceAll(String pattern,final String replacement) {
    final Pattern p = Pattern.compile(pattern);
    return new Function<String,String>() {
      public String apply(String input) {
        return p.matcher(input).replaceAll(replacement);
      }
    };
  } // end replace(String, String)
} // end class
...

private static final Function<String,String> myTransformer = Regexes.replaceAll("['\\\\]", "\\\\$0");

这不是番石榴解决方案(即使其中有Function),但它是我能够达到的最类似番石榴的解决方案,你仍然清楚地表明它是一个正则表达式(其中{{1没有。

答案 2 :(得分:0)

看起来您可以使用replaceFrom方法 或者这不是你真正想要的?

答案 3 :(得分:0)

所以你想要完全替换一个角色并将一些角色附加到另一个角色?为清楚起见,我可能会在两个单独的步骤中这样做。就个人而言,与简单替换一些易于理解的CharMatcher相比,我发现正则表达式正在做什么并不明显。