tarun14110 tarun14110 - 1 month ago 5
Java Question

replace multiple substrings in a string , Array vs HashMap

There are 2 functions defined below. They does the exactly same function i.e takes input a template (in which one wants to replace some substrings) and array of strings values( key value pair to replace, ex:[subStrToReplace1,value1,subStrToReplace1,value2,.....]) and returns the replaced String.

In second function I am iterating over words of the templates and searching for the relevant key if exist in hashmap and then next word. If I want to replace a word with some substring , which I again want to replace with some other key in values, I need to iterate over template twice. Thats what I did.

I would like to know which one should I use and why ? Any than alternative better than these are also welcome.

1st function

public static String populateTemplate1(String template, String... values) {
String populatedTemplate = template;
for (int i = 0; i < values.length; i += 2) {
populatedTemplate = populatedTemplate.replace(values[i], values[i + 1]);
}
return populatedTemplate;
}


2nd function

public static String populateTemplate2(String template, String... values) {
HashMap<String, String> map = new HashMap<>();
for (int i = 0; i < values.length; i += 2) {
map.put(values[i],values[i+1]);
}
StringBuilder regex = new StringBuilder();
boolean first = true;
for (String word : map.keySet()) {
if (first) {
first = false;
} else {
regex.append('|');
}
regex.append(Pattern.quote(word));
}
Pattern pattern = Pattern.compile(regex.toString());

int N0OfIterationOverTemplate =2;
// Pattern allowing to extract only the words
// Pattern pattern = Pattern.compile("\\w+");
StringBuilder populatedTemplate=new StringBuilder();;

String temp_template=template;

while(N0OfIterationOverTemplate!=0){
populatedTemplate = new StringBuilder();
Matcher matcher = pattern.matcher(temp_template);
int fromIndex = 0;
while (matcher.find(fromIndex)) {
// The start index of the current word
int startIdx = matcher.start();
if (fromIndex < startIdx) {
// Add what we have between two words
populatedTemplate.append(temp_template, fromIndex, startIdx);
}
// The current word
String word = matcher.group();
// Replace the word by itself or what we have in the map
// populatedTemplate.append(map.getOrDefault(word, word));

if (map.get(word) == null) {
populatedTemplate.append(word);
}
else {
populatedTemplate.append(map.get(word));
}

// Start the next find from the end index of the current word
fromIndex = matcher.end();
}
if (fromIndex < temp_template.length()) {
// Add the remaining sub String
populatedTemplate.append(temp_template, fromIndex, temp_template.length());
}

N0OfIterationOverTemplate--;
temp_template=populatedTemplate.toString();
}
return populatedTemplate.toString();
}

Answer

Definitively the first one for at least two reasons:

  1. It is easier to read and shorter, so it is easier to maintain as it is much less error prone
  2. You don't rely on a regular expression so it is faster by far