a=$b
b=oops
if your input string just has one of these, it will just be translated once as the programmer was probably expecting: input: foo $a bar
output: foo $b bar
but if your input string first references $b later, then it will recursively translate $a. input: foo $a bar $b
output: foo oops bar oops
Sometimes translating recursively is a bizarre behavior and possibly a security hole.The sane thing would be to loop through building the output string, adding the replacement for each symbol as you go. Using String.replace and the alreadyReplaced map is just a bad idea. Also inefficient, as it and throws away strings and does a redundant search on each loop iteration.
Feels typical of this whole '90s-era culture of arguing over refactoring with Java design patterns and ornate styles without ever thinking about if the algorithm is any good.
Edit: also, consider $foo $foobar. It doesn't properly tokenize on replacement, so this will also be wrong.