32

At the moment I'm doing

Example:

line.replaceAll(",","").replaceAll("cat","dog").replaceAll("football","rugby");

I think that it ugly. Not sure a better way to do this? Maybe loop through a hashmap?

EDIT:

By efficiency I mean better code style and flexibility

4
  • 4
    Is your question about runtime efficiency? Flexibility? Code style? Please clarify. Commented Oct 5, 2011 at 8:31
  • 2
    It may also be a question of correctness, for the replacements made during N passes may be not equivalent to performing replacements of N pairs during a single pass. Commented Oct 5, 2011 at 8:34
  • 2
    Updated question but looking for the code to be styled better and allow flexibility Commented Oct 5, 2011 at 8:35
  • 2
    similar question: stackoverflow.com/q/1326682/18511 Commented Oct 5, 2016 at 19:43

4 Answers 4

23

This functionality is already implemented in Commons Lang's StringUtils class.

StringUtils.replaceEach(String text, String[] searchList, String[] replacementList)
Sign up to request clarification or add additional context in comments.

3 Comments

I believe it is not in standard library but rather in Apache Commons link
New version would be the StrSubstitutor from Apache Commons Text.
StrSubstitutor seems to have a different purpose than a standard replace.
22

You can use Matcher.appendReplacement()/appendTail() to build very flexible search-and-replace features.

The example in the JavaDoc looks like this:

Pattern p = Pattern.compile("cat");
Matcher m = p.matcher("one cat two cats in the yard");
StringBuffer sb = new StringBuffer();
while (m.find()) {
    m.appendReplacement(sb, "dog");
}
m.appendTail(sb);
System.out.println(sb.toString());

Now, inside that while loop you can decide yourself what the replacement text is and base that information on the actual content being matched.

For example you could use the pattern (,|cat|football) to match ,, cat or football and decide on the actual replacement based on the actual match inside the loop.

You can make build even more flexible things this way, such as replacing all decimal numbers with hex numbers or similar operations.

It's not as short and simple as your code, but you can build short and simple methods with it.

5 Comments

What if you have hundreds of different words to check? The entire string would have to be scanned for each word, which is very inefficient.
@JackCole: no you wouldn't. Check the paragraph talking about the pattern with multiple words. You can still build a single pattern with any number of words.
Ah, I see now. You could follow up with a Map lookup of that word. I wonder how this performs in comparison to the above answer.
"For example you could use the pattern (,|cat|football) to match ,, cat or football and decide on the actual replacement based on the actual match inside the loop." Are you saying I could replace ',' with a '.' and 'cat' with 'dog' in one while loop? How does this look?
@Blaisem: exactly, that's what you can do. Inside the while loop simply inspect the return value of m.group() and the call àppendReplacement` with different second parameters based on what is returned.
4

Apart from that the actual replace is internally converted to a regex I think that approach is fine. A non-regex implementation can be found in StringUtils.replace(..) .

Looking at what alternatives there might be, you still need something to identify pairs of strings. This could look like:

MultiReplaceUtil.replaceAll{line, 
       {",", ""}, {"cat", "dog"}, {"football", "rugby"}};

or perhaps

MapReplaceUtil(String s, Map<String, String> replacementMap);

or even

ArrayReplaceUtil(String s, String[] target, String[] replacement);

neither of which seems more intuitive to me in terms of coding practice.

Comments

2

For Scala lovers:

"cat".r.replaceAllIn("one cat two cats in the yard", m => "dog")

With m you can even parameterize your replacement.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.