【问题标题】:Replace placeholders with Map values using indexOf使用 indexOf 将占位符替换为 Map 值
【发布时间】:2017-10-31 22:33:56
【问题描述】:

我正在尝试使用 indexOf 在字符串 ("${...}") 中查找占位符。 到目前为止,我下面的小示例运行良好,但显然仅适用于第一次出现。我如何更改此代码以能够遍历所有占位符并最终重建字符串。输入字符串可以是随机的,并且其中没有固定数量的占位符。不太确定从这里去哪里。

// example Hashmap
HashMap <String, String> placeHolderMap = new HashMap<String, String>();
placeHolderMap.put("name", "device");
placeHolderMap.put("status", "broken");
placeHolderMap.put("title", "smartphone");

// input String
String content = "This ${name} is ${status} and categorized as ${title} in the system";
int left = content.indexOf("${");
int right = content.indexOf("}");

// getting the name of the placeholder, if the placeholdermap contains the placeholder as a key it sets the placeholder to the corresponding value
String contentPlaceHolder = content.substring(left+2, right);
if (placeHolderMap.containsKey(contentPlaceHolder)){
    contentPlaceHolder = placeHolderMap.get(contentPlaceHolder);
}
content = content.substring(0, left) + contentPlaceHolder + content.substring(right+1);

目前,输出将是“此设备为 ${status} 并在系统中归类为 ${title}”

【问题讨论】:

标签: java string hashmap substring indexof


【解决方案1】:

你需要反复调用你的方法:

private String replace(String content) {
    int left = content.indexOf("${");
    if (left < 0) {
        // breaking the recursion
        return content;
    }
    int right = content.indexOf("}");

    // getting the name of the placeholder, if the placeholdermap contains the placeholder as a key it sets the placeholder to the corresponding value
    String contentPlaceHolder = content.substring(left + 2, right);
    if (placeHolderMap.containsKey(contentPlaceHolder)) {
        contentPlaceHolder = placeHolderMap.get(contentPlaceHolder);
    }
    content = content.substring(0, left) + contentPlaceHolder + content.substring(right + 1);
    return replace(content);
}

【讨论】:

  • 这可能有效,但“replaceAll”肯定是比 indexOf 和递归调用更优雅的解决方案?
  • @Neil 如果是作业并且指定不使用replaceAll?它只是使用了 OP 的规范
  • @Neil "replaceAll" 也有缺点。因为如果一个字符串有重复的占位符,它的行为就会出错。
  • @YuriHeiko 递归调用意味着如果您要替换超过 100 个字符串,此方法将崩溃。搜索${} 也不理想,因为如果字符串中有${ 而没有等效的},则会崩溃。总体而言,这不是一个非常强大的解决方案。 replaceAll 解决了这两个问题。
【解决方案2】:

为什么不使用 String.replaceAll() 方法?

    Map<String, String> placeHolderMap = new HashMap<>();
    placeHolderMap.put("\\$\\{name}", "device");
    placeHolderMap.put("\\$\\{status}", "broken");
    placeHolderMap.put("\\$\\{title}", "smartphone");


    // input String
    String content = "This ${name} is ${status} and categorized as ${title} in the system";

    for (Map.Entry<String, String> entry : placeHolderMap.entrySet()) {
          content = content.replaceAll(entry.getKey(), entry.getValue());
    }

更新 Stefan、Neil 和 Kennet,谢谢。

更新 17/07/17 您也可以使用不使用正则表达式的 String.replace() 方法,或者使用 Pattern.quote() 方法:

    Map<String, String> placeHolderMap = new HashMap<>();
    placeHolderMap.put("${name}", "device");
    placeHolderMap.put("${status}", "broken");
    placeHolderMap.put("${title}", "smartphone");


    // input String
    String content = "This ${name} is ${status} and categorized as ${title} in the system";

    for (Map.Entry<String, String> entry : placeHolderMap.entrySet()) {
          content = content.replace(entry.getKey(), entry.getValue());
          // content = content.replaceAll(Pattern.quote(entry.getKey()), entry.getValue());
    }

【讨论】:

  • String 是不可变的,因此如果您不保留返回值,则调用“replaceAll”将毫无用处。
  • String.replaceAll 使用正则表达式并给出 java.util.regex.PatternSyntaxException: Illegal repeat near index 0 ${title} 当您从 OP 示例更改占位符键时
  • 这对于我想要实现的目标来说似乎工作得很好,感谢大家的帮助!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-11
  • 2013-01-24
  • 1970-01-01
  • 2013-04-08
  • 1970-01-01
相关资源
最近更新 更多