用java8 lambda函数替换all
给定以下变量用java8 lambda函数替换all,java,lambda,java-8,Java,Lambda,Java 8,给定以下变量 templateText = "Hi ${name}"; variables.put("name", "Joe"); 我想使用以下代码将占位符${name}替换为值“Joe”(这不起作用) 但是,如果我采用“旧式”方式,一切都会完美运行: for (Entry<String, String> entry : variables.entrySet()){ String regex = "\\$\\{" + entry.getKey() + "\\}";
templateText = "Hi ${name}";
variables.put("name", "Joe");
我想使用以下代码将占位符${name}替换为值“Joe”(这不起作用)
但是,如果我采用“旧式”方式,一切都会完美运行:
for (Entry<String, String> entry : variables.entrySet()){
String regex = "\\$\\{" + entry.getKey() + "\\}";
templateText = templateText.replaceAll(regex, entry.getValue());
}
for(条目:variables.entrySet()){
字符串regex=“\\$\{”+entry.getKey()+“\\}”;
templateText=templateText.replaceAll(regex,entry.getValue());
}
我肯定在这里遗漏了一些东西:)import java.util.HashMap;
导入java.util.Map;
公共类Repl{
公共静态void main(字符串[]args){
Map variables=newhashmap();
String templateText=“嗨,${name}${secondname}!我的名字也是${name}:)”;
变量。put(“name”、“Joe”);
变量。put(“secondname”、“White”);
templateText=variables.keySet().stream().reduce(templateText,(acc,e)->acc.replaceAll(“\\$\\{”+e+“\\}”,variables.get(e));
System.out.println(模板文本);
}
}
输出:
嗨,乔·怀特!我的名字也是乔:)
然而,重新发明轮子并不是最好的主意,实现你想要的东西的首选方法是按规定使用
Map valuesMap=newhashmap();
价值Map.put(“动物”、“快速棕色狐狸”);
价值映射放置(“目标”、“懒狗”);
String templateString=“该${animal}跳过了${target}。”;
StrSubstitutor sub=新的StrSubstitutor(值MAP);
String resolvedString=sub.replace(templateString);
Java8
在Java 8中,实现这一点的正确方法没有改变,它基于/:
请注意,如注释中所述,appendReplacement()
的替换字符串可能包含使用$
符号的组引用,以及使用\
进行转义的组引用。如果不需要这样做,或者如果替换字符串可能包含这些字符,则应使用转义
在Java8中功能更强大
如果您想要更具Java-8风格的版本,可以将搜索和替换锅炉板代码提取到一个通用方法中,该方法采用替换函数:
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;
}
请注意,使用模式
作为参数(而不是字符串
)可以将其存储为常量,而不是每次重新编译
与上述有关$
和\
的注释相同–如果您不想让replacer
函数处理它,您可能希望在replaceAll()
方法中强制执行quoteReplacement()
Java 9及以上版本
引入了Java9,它基本上实现了与上述功能版本相同的东西。有关更多详细信息,请参阅。您的代码应按如下所示进行更改
String templateText = "Hi ${name}";
Map<String,String> variables = new HashMap<>();
variables.put("name", "Joe");
templateText = variables.keySet().stream().reduce(templateText, (originalText, key) -> originalText.replaceAll("\\$\\{" + key + "\\}", variables.get(key)));
String templateText=“Hi${name}”;
Map variables=newhashmap();
变量。put(“name”、“Joe”);
templateText=variables.keySet().stream().reduce(templateText,(originalText,key)->originalText.replaceAll(“\\$\\{”+key+“\\}”,variables.get(key));
您也可以使用
身份
identity
是还原功能的初始值,即累加器
累加器
累加器
将标识
还原为结果
,如果流是顺序,则下一次还原的标识
组合器
此函数不能在流中按顺序调用。它从并行流中的identity
和结果
计算下一个identity
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);
BinaryOperator CombinerVerbeCalledInSequentialyStream=(标识,t)->{
抛出新的IllegalStateException(“不能在并行流中使用”);
};
字符串结果=variables.entrySet().stream()
.reduce(模板文本)
,(it,var)->it.replaceAll(格式(“\\$\\{%s\\}”,var.getKey())
,var.getValue())
,合并逐行调用顺序流);
重复执行replaceAll
,即对于每个可替换变量,可能会变得非常昂贵,尤其是随着变量数量的增加。当使用流API时,这不会变得更有效。regex包包含更有效地执行此操作所需的构建块:
public static String replaceAll(String template, Map<String,String> variables) {
String pattern = variables.keySet().stream()
.map(Pattern::quote)
.collect(Collectors.joining("|", "\\$\\{(", ")\\}"));
Matcher m = Pattern.compile(pattern).matcher(template);
if(!m.find()) {
return template;
}
StringBuffer sb = new StringBuffer();
do {
m.appendReplacement(sb, Matcher.quoteReplacement(variables.get(m.group(1))));
} while(m.find());
m.appendTail(sb);
return sb.toString();
}
m.group(0)
是实际匹配项,因此使用它作为替换字符串的回退,可以在键不在映射中时建立不替换${…}
的原始行为。如前所述,其他行为,如报告缺少的键或使用不同的回退文本,都是可能的。要更新@didier-l的答案,在Java 9中这是一行
Pattern.compile("[$][{](.+?)[}]").matcher(templateText).replaceAll(m -> variables.get(m.group(1)))
forEach
在每个元素上运行您的命令,但您没有捕获结果。此外,如果您不尝试使用正则表达式,它将更易于使用,而不是感谢。那么,您能告诉我使用Java8的正确方法吗?请注意,在您的Java8版本中,正则表达式的前缀中似乎也有一个输入错误:“\\{$\\{”
,而不是“\\\$\{”
。您是对的。我刚刚编辑过。谢谢,您能解释一下(函数)是什么吗代表?此外,你能解释一下reduce部分吗?谢谢:)这是不必要的复杂,你可以只做.reduce(templateText,(acc,e)->acc.replaceAll(\\$\{e+“\\}”,variables.get(e));
(确保不要使用并行流)但是那样的话,你就不能很容易地并行化你的流,而这在你以前的版本中是可行的;-)然而,这甚至不是一个要求,所以这样可能没问题:-)的解决方案违反了该方法的要求:identity
值必须是累加器函数的一个标识。这意味着对于所有t
,累加器。应用(标识,t)
等于t
Pattern variablePattern = Pattern.compile("\\$\\{(.+?)\\}");
StringBuffer result = replaceAll(templateText, variablePattern,
m -> variables.get(m.group(1)));
String templateText = "Hi ${name}";
Map<String,String> variables = new HashMap<>();
variables.put("name", "Joe");
templateText = variables.keySet().stream().reduce(templateText, (originalText, key) -> originalText.replaceAll("\\$\\{" + key + "\\}", variables.get(key)));
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);
public static String replaceAll(String template, Map<String,String> variables) {
String pattern = variables.keySet().stream()
.map(Pattern::quote)
.collect(Collectors.joining("|", "\\$\\{(", ")\\}"));
Matcher m = Pattern.compile(pattern).matcher(template);
if(!m.find()) {
return template;
}
StringBuffer sb = new StringBuffer();
do {
m.appendReplacement(sb, Matcher.quoteReplacement(variables.get(m.group(1))));
} while(m.find());
m.appendTail(sb);
return sb.toString();
}
private static Pattern VARIABLE = Pattern.compile("\\$\\{([^}]*)\\}");
public static String replaceAll(String template, Map<String,String> variables) {
Matcher m = VARIABLE.matcher(template);
if(!m.find())
return template;
StringBuffer sb = new StringBuffer();
do {
m.appendReplacement(sb,
Matcher.quoteReplacement(variables.getOrDefault(m.group(1), m.group(0))));
} while(m.find());
m.appendTail(sb);
return sb.toString();
}
Pattern.compile("[$][{](.+?)[}]").matcher(templateText).replaceAll(m -> variables.get(m.group(1)))