tags:

views:

609

answers:

6
+2  Q: 

java replaceLast()

Is there replaceLast() in Java?
I saw there is replaceFirst()

EDIT: If there is not in the SDK, what would be a good implementation?

+3  A: 

See for yourself: String

Or is your question actually "How do I implement a replaceLast()?"

Let me attempt an implementation (this should behave pretty much like replaceFirst(), so it should support regexes and backreferences in the replacement String):

public static String replaceLast(String input, String regex, String replacement) {
    Pattern pattern = Pattern.compile(regex);
    Matcher matcher = pattern.matcher(input);
    if (!matcher.find()) {
       return input;
    }
    int lastMatchStart=0;
    do {
      lastMatchStart=matcher.start();
    } while (matcher.find());
    matcher.find(lastMatchStart);
    StringBuffer sb = new StringBuffer(input.length());
    matcher.appendReplacement(sb, replacement);
    matcher.appendTail(sb);
    return sb.toString();
}
Joachim Sauer
+1 for smugness
willcodejavaforfood
@willcode: it was intended as a semi-honest, semi-smug question ;-)
Joachim Sauer
@Joachim - Yes I did not see it as being pure evil :)
willcodejavaforfood
+1  A: 

No.

You could do reverse / replaceFirst / reverse, but it's a bit expensive.

Thomas
+ you will need to reverse the search string, so that's 3 reverse operations.
Fortega
+1  A: 

You can combine StringUtils.reverse() with String.replaceFirst()

Mihir Mathuria
abcdefg will be gfedcba, you have to modify your regex to replace the "reversed" target.
Joset
+2  A: 

For a solution, see this SO question.

However, it does not work with regexes...

Fortega
This solution does a char-by-char replacement, not a fullfledged `replaceLast()`.
BalusC
+2  A: 

If you don't need regex, here's a substring alternative.

public static String replaceLast(String string, String toReplace, String replacement) {
    int pos = string.lastIndexOf(toReplace);
    if (pos > -1) {
        return string.substring(0, pos)
             + replacement
             + string.substring(pos + toReplace.length(), string.length());
    } else {
        return string;
    }
}

Testcase:

public static void main(String[] args) throws Exception {
    System.out.println(replaceLast("foobarfoobar", "foo", "bar")); // foobarbarbar
    System.out.println(replaceLast("foobarbarbar", "foo", "bar")); // barbarbarbar
    System.out.println(replaceLast("foobarfoobar", "faa", "bar")); // foobarfoobar
}
BalusC
Ah, yeah - just that this doesn't replace regexps... (think s/ab*c/d/)
Thomas
@Thomas, it also states "If you don't need regex..." in top of answer :)
BalusC
+4  A: 

It could (of course) be done with regex:

public class Test {

    public static String replaceLast(String text, String regex, String replacement) {
        return text.replaceFirst("(?s)"+regex+"(?!.*?"+regex+")", replacement);
    }

    public static void main(String[] args) {
        System.out.println(replaceLast("foo AB bar AB done", "AB", "--"));
    }
}

although a bit cpu-cycle-hungry with the look-aheads, but that will only be an issue when working with very large strings (and many occurrences of the regex being searched for).

A short explanation (in case of the regex being AB):

(?s)     # enable dot-all option
A        # match the character 'A'
B        # match the character 'B'
(?!      # start negative look ahead
  .*?    #   match any character and repeat it zero or more times, reluctantly
  A      #   match the character 'A'
  B      #   match the character 'B'
)        # end negative look ahead
Bart Kiers