给定以下变量
templateText = "Hi ${name}";
variables.put("name", "Joe");我希望使用以下代码(不起作用)将占位符${name}替换为值"Joe“
variables.keySet().forEach(k -> templateText.replaceAll("\\${\\{"+ k +"\\}" variables.get(k)));然而,如果我采用“老派”的方式,一切都会很完美:
for (Entry<String, String> entry : variables.entrySet()){
String regex = "\\$\\{" + entry.getKey() + "\\}";
templateText = templateText.replaceAll(regex, entry.getValue());
}当然,我在这里遗漏了一些东西:)
发布于 2017-04-12 15:46:34
您也可以使用Stream.reduce(标识、累加器、组合器)。
身份
identity是还原函数的初值,即accumulator。
累加器
accumulator将identity还原为result,如果流为顺序,则为下一次还原的identity。
组合器
这个函数永远不会在中按顺序调用流。在并行identity流中,从identity & result中计算下一个。
BinaryOperator<String> combinerNeverBeCalledInSequentiallyStream=(identity,t) -> {
throw new IllegalStateException("Can't be used in parallel stream");
};
String result = variables.entrySet().stream()
.reduce(templateText
, (it, var) -> it.replaceAll(format("\\$\\{%s\\}", var.getKey())
, var.getValue())
, combinerNeverBeCalledInSequentiallyStream);发布于 2017-04-12 14:19:05
Java 8
实现这一点的正确方法在Java 8中没有改变,它基于appendReplacement()/appendTail()
Pattern variablePattern = Pattern.compile("\\$\\{(.+?)\\}");
Matcher matcher = variablePattern.matcher(templateText);
StringBuffer result = new StringBuffer();
while (matcher.find()) {
matcher.appendReplacement(result, variables.get(matcher.group(1)));
}
matcher.appendTail(result);
System.out.println(result);注意,正如凿岩机在注释中提到的,appendReplacement()的替换字符串可能包含使用$符号的组引用,以及使用\进行转义。如果这是不需要的,或者如果替换字符串可能包含这些字符,则应该使用Matcher.quoteReplacement()转义它们。
在Java 8中更有功能
如果您想要更多的Java-8风格的版本,您可以将搜索和替换锅炉板代码提取为一个采用替换Function的通用方法。
private static StringBuffer replaceAll(String templateText, Pattern pattern,
Function<Matcher, String> replacer) {
Matcher matcher = pattern.matcher(templateText);
StringBuffer result = new StringBuffer();
while (matcher.find()) {
matcher.appendReplacement(result, replacer.apply(matcher));
}
matcher.appendTail(result);
return result;
}并把它当作
Pattern variablePattern = Pattern.compile("\\$\\{(.+?)\\}");
StringBuffer result = replaceAll(templateText, variablePattern,
m -> variables.get(m.group(1)));请注意,以Pattern作为参数(而不是String)允许将其作为常量存储,而不是每次重新编译。
同样的注释也适用于$和\ --如果您不希望使用replacer函数来处理它,您可能希望在replaceAll()方法中强制执行quoteReplacement()。
Java 9及以上
Java9引入了Matcher.replaceAll(Function),它基本上实现了与上面的功能版本相同的功能。有关更多详细信息,请参阅杰西·格利克的回答。
发布于 2017-04-12 14:11:11
import java.util.HashMap;
import java.util.Map;
public class Repl {
public static void main(String[] args) {
Map<String, String> variables = new HashMap<>();
String templateText = "Hi, ${name} ${secondname}! My name is ${name} too :)";
variables.put("name", "Joe");
variables.put("secondname", "White");
templateText = variables.keySet().stream().reduce(templateText, (acc, e) -> acc.replaceAll("\\$\\{" + e + "\\}", variables.get(e)));
System.out.println(templateText);
}
}产出:
嗨乔·怀特!我也叫乔:)
但是,重新发明轮子并不是最好的主意,实现您想要的东西的首选方法是使用阿帕奇公域朗作为声明的这里。
Map<String, String> valuesMap = new HashMap<String, String>();
valuesMap.put("animal", "quick brown fox");
valuesMap.put("target", "lazy dog");
String templateString = "The ${animal} jumped over the ${target}.";
StrSubstitutor sub = new StrSubstitutor(valuesMap);
String resolvedString = sub.replace(templateString);https://stackoverflow.com/questions/43371521
复制相似问题