You can perform the substitutions in a single pass. Arrange for the text to be stored as a single string so that you can operate on the input in bulk. You can use an appropriate delimiter so that you can separate the strings when the translation is done.
Prepare a regular expression (or generate a state machine based tokenizer using a tool like JFlex) that matches any of the strings to be replaced (the keys in your map). Then iterate over each match and perform the substitution.
Here's an example of using Pattern to perform the replacements in bulk:
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import java.util.stream.Collectors;
public class Substituter {
public static void main(String args[]) {
// Read the input into a string (or combine the inputs if needed)
List<String> strings = Arrays.asList("I'm a cat", "dog", "There's an elephant and I'm seeing", "we're five");
// String replacements
Map<String, String> replacements = new HashMap<>();
replacements.put("I'm", "I am");
replacements.put("we're", "we are");
replacements.put("There's", "there is");
// Build the regular expression by concatenating the strings to be replaced into an or expression (|)
Pattern pattern = Pattern.compile(replacements.keySet().stream().map(Pattern::quote).collect(Collectors.joining("|")));
// Perform the substitutions
Matcher m = pattern.matcher(String.join("~", strings));
StringBuffer newText = new StringBuffer();
while (m.find()) {
m.appendReplacement(newText, replacements.get(m.group()));
}
m.appendTail(newText);
// Split the output into separate strings if needed
List<String> newStrings = Arrays.asList(newText.toString().split("~"));
System.out.println("Original strings: " + strings);
System.out.println("New strings: " + newStrings);
}
}
Output:
Original strings: [I'm a cat, dog, There's an elephant and I'm seeing, we're five]
New strings: [I am a cat, dog, there is an elephant and I am seeing, we are five]