32

I'm looking for the best approach for string find and replace in Java.

This is a sentence: "My name is Milan, people know me as Milan Vasic".

I want to replace the string Milan with Milan Vasic, but on place where I have already Milan Vasic, that shouldn't be a case.

after search/replace result should be: "My name is Milan Vasic, people know me as Milan Vasic".

I was try to use indexOf() and also Pattern/Matcher combination, but neither of my results not looks elegant, does someone have elegant solution?

cheers!

2
  • 1
    What about Milan Bandic in such case? Let's have one Milan Vasic and one Milan Bandic in same sentence, so system will ignore first Milan, second will be Milan Vasic Bandic? :) Commented Jan 12, 2010 at 14:43
  • Heheeh...I was use my name for this example :) Commented Jan 12, 2010 at 14:54

7 Answers 7

48

Well, you can use a regular expression to find the cases where "Milan" isn't followed by "Vasic":

Milan(?! Vasic)

and replace that by the full name:

String.replaceAll("Milan(?! Vasic)", "Milan Vasic")

The (?!...) part is a negative lookahead which ensures that whatever matches isn't followed by the part in parentheses. It doesn't consume any characters in the match itself.

Alternatively, you can simply insert (well, technically replacing a zero-width match) the last name after the first name, unless it's followed by the last name already. This looks similar, but uses a positive lookbehind as well:

(?<=Milan)(?! Vasic)

You can replace this by just " Vasic" (note the space at the start of the string):

String.replaceAll("(?<=Milan)(?! Vasic)", " Vasic")

You can try those things out here for example.

Sign up to request clarification or add additional context in comments.

4 Comments

Use java.lang.String.replaceAll(String, String)
Well, could be more elegant but when you know regular expressions it isn't too hard to read.
exactly, I'm in learning process of regex :) what will be the vice versa solution for example if I have "Vasic" and want to replace with "Milan Vasic", I mean with leading word?
You'd change the lookbehind into a negative one: (?<!Milan ) and the lookahead into a positive: (?=Vasic).
25

Another option:

"My name is Milan, people know me as Milan Vasic"
    .replaceAll("Milan Vasic|Milan", "Milan Vasic"))

2 Comments

Thanks man, this could be very handy as well as first response!
It is not elegant. It does useless replacements.
10

One possibility, reducing the longer form before expanding all:

string.replaceAll("Milan Vasic", "Milan").replaceAll("Milan", "Milan Vasic")

Another way, treating Vasic as optional:

string.replaceAll("Milan( Vasic)?", "Milan Vasic")

Others have described solutions based on lookahead or alternation.

2 Comments

nice... but regex already let you indicate non capturing groups: (?! Milan)
That's a negative lookahead. Non-capturing groups would be (?: ...)
5

When you dont want to put your hand yon regular expression (may be you should) you could first replace all "Milan Vasic" string with "Milan".

And than replace all "Milan" Strings with "Milan Vasic".

Comments

4

Simply include the Apache Commons Lang JAR and use the org.apache.commons.lang.StringUtils class. You'll notice lots of methods for replacing Strings safely and efficiently.

You can view the StringUtils API at the previously linked website.

"Don't reinvent the wheel"

4 Comments

@ArtOfWarfare Maven and Gradle just work, and unlike most languages you don't need to build dependencies, just pull them. So this isn't a good reason in the slightest. There may be better still dependency management systems out there but PIP isn't it (relevant xkcd: xkcd.com/1987)
@ArtOfWarfare I also have years of experience with Maven and I would never choose to write something myself just because I need to add a few lines of XML. Is my point.
@ArtOfWarfare agreed on using regex and this answer desperately needs a code example, also Java String could use some more utility methods, but please for everyone's sake try to minimize the sweeping diatribes about Java as a whole, it is distracting to people seeking answers and is not appropriate imho.
@drrob - Yeah. No need to talk about it. Irrelevant to the question. I deleted my earlier comments. Just leaving this one: I’m downvoting this answer because Java has perfectly serviceable regex functions built in. There’s no need to involve third party libraries. This answer also doesn’t say why or how to use those third party libraries.
4

Try this:

public static void main(String[] args) {
    String str = "My name is Milan, people know me as Milan Vasic.";

    Pattern p = Pattern.compile("(Milan)(?! Vasic)");
    Matcher m = p.matcher(str);

    StringBuffer sb = new StringBuffer();

    while(m.find()) {
        m.appendReplacement(sb, "Milan Vasic");
    }

    m.appendTail(sb);
    System.out.println(sb);
}

1 Comment

This is a nice illustration of the general case, in which the replacement may be computed at runtime.
2

you can use pattern matcher as well, which will replace all in one shot.

Pattern keyPattern = Pattern.compile(key); Matcher matcher = keyPattern.matcher(str); String nerSrting = matcher.replaceAll(value);

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.