我想替换一些字符集,并且为了这个目的使用了CharMatcher的番石榴,现在我需要增强一个方法 - 现在我需要替换一些字符,就像' %' - > '!%',我不知道如何用番石榴这样做,所以在阅读this question后,我使用了正则表达式。和代码类似 -
s.replaceAll("['\\\\]", "\\\\$0");
但它是同一方法的一部分,并且在相同的字符串操作方法中使用CharMather和regex看起来不太一致,所以我只是想知道我是否也可以将CharMatcher用于此目的。
我没有测试正则表达式方法是否比CharMatcher更快,反之亦然,但如果CharMatcher可以处理这个问题,那么我们想知道如何知道哪种方法更有效。
答案 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
相比,我发现正则表达式正在做什么并不明显。