7

What is the fastest way in java to replace multiple placeholders.

For example: I have a String with multiple placeholder, each has string placeholder name.

String testString = "Hello {USERNAME}! Welcome to the {WEBSITE_NAME}!";

And a Map which contains the map of what value will be placed in which placeholder.

Map<String, String> replacementStrings = Map.of(
                "USERNAME", "My name",
                "WEBSITE_NAME", "My website name"
        );

What is the fastest way in java to replace all the placeholder from Map. Is it possible to update all placeholders in one go?

(Please note, I cannot change the placeholder format to {1}, {2} etc)

Tamanna_24
  • 93
  • 1
  • 1
  • 5
  • the question looks similar. The difference is I wanted to know if I can do that in one go( not replacing the String as many time as my Map keyset) I can possibly do that by some similar code(for loop and logic), but would love to find out if there is already something in Java which does this. – Tamanna_24 Apr 19 '19 at 13:42
  • If there is a nice one-liner it would be a valid answer to that question, so I doubt there is one. There might be some library that does this, but in the end there will be a loop looping the map/string either way. – Ivar Apr 19 '19 at 13:49
  • I see :( In that case I will close the question. – Tamanna_24 Apr 19 '19 at 13:55
  • Tokenize the text and replace by iterating the tokens once from left to right. The answers suggesting `replace` or `replaceAll` will all need a full pass each and your performance might then degrade. This will become a factor when your map contains maybe 1000 or more entries. – Zabuzard Apr 19 '19 at 13:58
  • @Zabuza this is exactly my concern! For my case, each key will appear exactly once, so I don't need a full pass. – Tamanna_24 Apr 19 '19 at 14:17

2 Answers2

14

You can try with StrSubstitutor (Apache Commons)

String testString = "Hello {USERNAME}! Welcome to the {WEBSITE_NAME}!";
Map<String, String> replacementStrings = Map.of(
                "USERNAME", "My name",
                "WEBSITE_NAME", "My website name"
        );
StrSubstitutor sub = new StrSubstitutor(replacementStrings , "{", "}");
String result = sub.replace(testString );
Zabuzard
  • 25,064
  • 8
  • 58
  • 82
Vikas
  • 6,868
  • 4
  • 27
  • 41
0

You can use below method to do so:

public static String replacePlaceholderInString(String text, Map<String, String> map){
    Pattern contextPattern = Pattern.compile("\\{[\\w\\.]+\\}");
    Matcher m = contextPattern .matcher(text);
    while(m.find()){
        String currentGroup = m.group();
        String currentPattern = currentGroup.replaceAll("^\\{", "").replaceAll("\\}$", "").trim();
        String mapValue = map.get(currentPattern);
        if (mapValue != null){
            text = text.replace(currentGroup, mapValue);
        }
    }
    return text;
}
  • The inner `replaceAll` should rather be `currentGroup.substring(1, currentGroup.length() - 1)`. – Roland Illig Apr 19 '19 at 14:01
  • What if the replacement map contains an entry that maps `a` to `{a} {a} {a}`? – Roland Illig Apr 19 '19 at 14:03
  • replacing curly braces with empty string or using substring are same thing. performance wise i think substring will perform better. we should use substring. thanks –  Apr 20 '19 at 05:40
  • if map contains a to {a} {a} {a} then, this method replace only key, not the values in map everytime, otherwise it will create an infinite loop. –  Apr 20 '19 at 05:42