【问题标题】:Insert string keyword values based map keys in main string在主字符串中插入基于映射键的字符串关键字值
【发布时间】:2019-09-16 13:29:51
【问题描述】:

在 Java 中,我必须根据主字符串中的键插入字符串值。 比如——

主字符串 -

sellers(seller: $sellerId, shipment: $shipmentId)

键值映射——

{
    sellerId: abc
    shipmentId: 123
}

所以插入后会变成

sellers(seller: abc, shipment: 123)

我知道我可以进行字符串替换。但这似乎不是一个好方法。所以只是想知道这里有没有标准方法或更好的做事方式?

【问题讨论】:

标签: java


【解决方案1】:

您可以考虑两种方法:

1 - 遍历映射条目,并进行简单的字符串替换(请注意,这假定字符串中每个 var 都出现一次;如果不是这种情况,则需要使用 replaceAll):

String text = "sellers(seller: $sellerId, shipment: $shipmentId)";
Map<String, Object> binding = ...;

String result = text;
for (Entry<String, Object> entry : binding.entrySet()) {
    result = result.replace("$" + entry.getKey(), String.valueOf(entry.getValue()));
}

2 - 对于高级用例,您希望使用适当的模板引擎。这是一个使用groovy's simple template engine 的示例(在java 中通过添加groovy jar 使用):

groovy.text.SimpleTemplateEngine engine = new groovy.text.SimpleTemplateEngine();
Writable template = engine.createTemplate(text).make(binding);

String result = template.toString();

请注意,groovy 会替换以 $ 为前缀的变量名,这就是为什么它无需更改即可工作(使其成为您当前语法的好选择)。

两者都会产生您预期的结果,但您必须根据结果进行选择。

【讨论】:

    【解决方案2】:

    这里可以选择字符串格式

    Map<String, Integer> yourMap = new HashMap<>();
    yourMap.put("abc", 123);
    
    for (Map.Entry<String, Integer> entry : yourMap.entrySet()) {
       String output = String.format("sellers(seller: %s, shipment: %d)", entry.getKey(), entry.getValue());
       System.out.println("output = " + output);
    }
    

    【讨论】:

      【解决方案3】:

      根据地图可以容纳的值,您可能会遇到一些问题。例如,如果值可能包含其他键标识符,例如

      {
          foo: $bar
          bar: 123
      }
      

      然后使用一系列replace(mapEntryKey, mapEntryValue) 可以改变字符串像

      abc $foo efg $bar 
      

      先进入$foo-&gt;$bar

      abc $bar efg $bar
      

      然后$bar-&gt;123

      abc 123 efg 123
      

      这不是我们想要的。

      为避免此类问题,我们应该只对模板进行一次迭代,搜索每个 $key 并将其替换为存储在 map 中的值。如果 map 不包含这样的键,我们可以保留它(用它自己替换它)。

      我们可以使用Matcher#replaceAll​(Function&lt;MatchResult,​String&gt; replacer) 来做到这一点。顺便说一句,如果映射值可以包含 $\ 这也是替换的元字符,我们需要对它们进行转义。为此,我们可以使用Mather#quoteReplacement 方法。

      演示:

      Map<String, String> map = Map.of("sellerId", "abc",
              "shipmentId", "123");
      String yourTemplate = "sellers(seller: $sellerId, shipment: $shipmentId)";
      
      Pattern p = Pattern.compile("\\$(\\w+)");
      Matcher m = p.matcher(yourTemplate);
      
      String replaced = m.replaceAll(match -> {
          if(map.containsKey(match.group(1))){
              return Matcher.quoteReplacement(map.get(match.group(1)));
          }else{
              return Matcher.quoteReplacement(match.group());
          }
      });
      System.out.println(replaced);
      

      输出:sellers(seller: abc, shipment: 123)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-07-15
        • 2018-04-27
        • 1970-01-01
        相关资源
        最近更新 更多