用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)
等于
tPattern 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)))