当前位置: 首页 > 知识库问答 >
问题:

用java8 lambda函数替换All

萧树
2023-03-14

给定以下变量

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());           
   }

)我一定漏了点什么

共有2个答案

陈龙野
2023-03-14

实现这一点的正确方式在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);

请注意,正如drrob在注释中提到的,appendreplacement()的替换字符串可能包含使用$符号的组引用,并使用\进行转义。如果不希望这样做,或者替换字符串可能包含这些字符,则应使用matcher.quoterePlacement()转义它们。

如果您想要一个更像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;
}

并将其用作

Pattern variablePattern = Pattern.compile("\\$\\{(.+?)\\}");
StringBuffer result = replaceAll(templateText, variablePattern,
                                 m -> variables.get(m.group(1)));

请注意,使用patter作为参数(而不是string)允许将其存储为常量,而不是每次都重新编译它。

与上面关于$\的说明相同-如果您不希望ReplaceAll()函数处理QuoterePlace()方法,您可能希望在ReplaceAll()方法中强制执行QuoterePlace()

Java 9引入了matcher.replaceAll(Function),它基本上实现了与上面的函数版本相同的东西。更多细节见杰西·格利克的回答。

廖琨
2023-03-14

您还可以使用stream.reduce(标识、累加器、组合器)。

identity是约简函数的初始值,约简函数是accumulator

累加器标识还原为结果,如果流是顺序的,则该标识是下一次还原的标识

这个函数永远不要在顺序流中调用。它在并行流中从标识结果中计算下一个标识

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);
 类似资料:
  • 问题内容: 给定以下变量 我想使用以下代码将占位符$ {name}替换为值“ Joe”(不起作用) 但是,如果我采用“旧式”方式,则一切都将正常运行: 我肯定在这里想念的东西:) 问题答案: 您还可以使用Stream.reduce(identity,accumulator,combiner)。 身份 是减少函数的初始值。 累加器 减少到,如果流是 顺序的 ,这是下一个减少的条件。 合路器 永远不要

  • null 我读过PDO的书。如何使用MySQL或MSSQL将代码更新为PDO?

  • 我用Mockito写UT,我想替换我的mock函数(哪个DB选择操作) 使用我在测试类中编写的新函数(使用map模拟数据库选择); 我想用正确的键输入返回正确的值 我试图这样做使用ArgumentCaptor如下,但它没有工作,因为我想 我想当调用dataBaseSelect.selectDataFromDB时,它将被模拟,然后从MapSelect.selectDataFromMap返回结果,参数

  • 函数名称:字符串替换 函数功能:字符串替换 函数方法 str,num = string.gsub(s,pattern,repl,n) 参数 类型 必填 说明 s string/table/number 是 原字符串 pattern string/table/number 是 待查找的字符串或模式匹配 repl string/table/number 是 待替换的字符串 n number 否 替换次

  • 问题内容: 我在Java 8映射操作中传递了一个Function,Intellij告诉我可以将其替换为lambda表达式。但是我不知道如何在不创建中间对象结构的情况下做到这一点。 这是我的工作: 我认为Intellij建议我这样做: 我不知道一种干净的方法来获取在匿名函数中检索到的objectType.getTempUrl()。getFullUrl()部分,有什么建议吗? 问题答案: 你总是可以写

  • 我正在尝试将登录用户的详细信息提供给我的应用程序。我有以下代码在Angular 5中工作,但在Angular 6中不工作,因为. share()函数在rxjs 6中丢失 我需要这个吗。share()函数?关于rxjs 6的更改,我的代码看起来还好吗?