我一直在尝试设计一个用Pattern / Matcher实例替换多个String#replaceAll调用的方法,希望它比我当前替换字符串中的文本的方法更快,但我不确定如何去做。
以下是我想要操作的String的示例:
@bla@This is a @red@line @bla@of text.
如您所见,有多个@字符,中间有3个字符;情况总是如此。如果我想替换'@ xxx @'的每个实例(其中xxx可以是从0到9的任何小写字母或数字),那么最有效的方法是什么呢?目前我正在存储一个Map,其键是'@ xxx @'子串,并且值是我想要替换特定子串的值;我检查整个String是否包含'@ xxx @'子串,并为每个实例调用replaceAll方法,但我认为这是非常低效的。
非常感谢!
TL; DR - 使用不同的String替换String的子串的Pattern / Matcher是否比检查String是否包含子串并使用String#replaceAll更有效?如果是这样,我该怎么做呢?
答案 0 :(得分:3)
对于另一个类似的问题,这是previous answer的更动态版本。
这是一个帮助方法,用于搜索您想要的任何@keyword@
。他们不必长达3个字符。
private static String replace(String input, Map<String, String> replacement) {
StringJoiner regex = new StringJoiner("|", "@(", ")@");
for (String keyword : replacement.keySet())
regex.add(Pattern.quote(keyword));
StringBuffer output = new StringBuffer();
Matcher m = Pattern.compile(regex.toString()).matcher(input);
while (m.find())
m.appendReplacement(output, Matcher.quoteReplacement(replacement.get(m.group(1))));
return m.appendTail(output).toString();
}
测试
Map<String,String> replacement = new HashMap<>();
replacement.put("bla", "hello,");
replacement.put("red", "world!");
replacement.put("Hold", "wait");
replacement.put("Better", "more");
replacement.put("a?b*c", "special regex characters");
replacement.put("foo @ bar", "with spaces and the @ boundary character work");
System.out.println(replace("@bla@This is a @red@line @bla@of text", replacement));
System.out.println(replace("But @Hold@, this can do @Better@!", replacement));
System.out.println(replace("It can even handle @a?b*c@ without dying", replacement));
System.out.println(replace("Keyword @foo @ bar@ too", replacement));
输出
hello,This is a world!line hello,of text
But wait, this can do more!
It can even handle special regex characters without dying
Keyword with spaces and the @ boundary character work too
答案 1 :(得分:2)
对于appendReplacement
来说,这是一个相对简单的案例:
// Prepare map of replacements
Map<String,String> replacement = new HashMap<>();
replacement.put("bla", "hello,");
replacement.put("red", "world!");
// Use a pattern that matches three non-@s between two @s
Pattern p = Pattern.compile("@([^@]{3})@");
Matcher m = p.matcher("@bla@This is a @red@line @bla@of text");
StringBuffer sb = new StringBuffer();
while (m.find()) {
// Group 1 captures what's between the @s
String tag = m.group(1);
String repString = replacement.get(tag);
if (repString == null) {
System.err.println("Tag @"+tag+"@ is unexpected.");
continue;
}
// Replacement could have special characters, e.g. '\'
// Matcher.quoteReplacement() will deal with them correctly:
m.appendReplacement(sb, Matcher.quoteReplacement(repString));
}
m.appendTail(sb);
String result = sb.toString();