James
James

Reputation: 571

Java Matcher.appendReplacement() and Matcher.appendTail() for StringBuilder?

Is there an alternative to Matcher.appendReplacement() and Matcher.appendTail() which takes StringBuilder instead of StringBuffer ?

Is there an 'easy' way to 'convert' Java code which calls Matcher with a StringBuffer to use StringBuilder instead?

Thanks, James

Upvotes: 7

Views: 4673

Answers (3)

Grigory Kislin
Grigory Kislin

Reputation: 18010

So, for readers: full code for JDK 9 and multiple replacement (e.g. "Hello ${name}, check ${email}"):

private static final Pattern PLACEHOLDER_PATTERN = Pattern.compile("\\$\\{(\\w+)}");

Matcher matcher = PLACEHOLDER_PATTERN.matcher(value)
if(matcher.find()){
    StringBuilder sb = new StringBuilder();
    while (p.matcher.find()) {
       String key = p.matcher.group(1);
       Object obj = getObject(key, map);
       p.matcher.appendReplacement(sb, obj.toString());
    }
    p.matcher.appendTail(sb);
    return sb.toString;
}

Upvotes: 0

Mena
Mena

Reputation: 48404

Short answer, no.

This is as per API in latest Java 8 at the time of writing.

However, one of the overloaded StringBuffer constructors takes a CharSequence as parameter, and StringBuilder (just like StringBuffer) IS-A CharSequence.

For instance:

matcher.appendReplacement(
    new StringBuffer(yourOriginalStringBuilder), "yourReplacement"
);

Edit

Since Java 9, an overload is available, which takes a StringBuilder instead - see API here.

Upvotes: 4

mmm444
mmm444

Reputation: 193

Short answer, not yet. Not until Java 9. In Java 9 there are Matcher.appendReplacement(StringBuilder,String) and Matcher.appendTail(StringBuilder) methods added to the API.

Until then if you don't need group substitutions in replacement string then I still find this solution 'easy':

Matcher m = PATTERN.matcher(s);
StringBuilder sb = new StringBuilder();
int pos = 0;
while(m.find()) {
    sb.append(s, pos, m.start());
    pos = m.end();
    sb.append("replacement")
}
sb.append(s, pos, s.length());

And even if you need group subtitutions then it gets just 'moderately' difficult:

Matcher m = PATTERN.matcher(s);
StringBuilder sb = new StringBuilder();
int pos = 0;
while(m.find()) {
    sb.append(s, pos, m.start());
    pos = m.end();
    if (m.start(1) >= 0) {                  // check if group 1 matched
        sb.append(s, m.start(1), m.end(1)); // replace with group 1
    }
}
sb.append(s, pos, s.length());

Upvotes: 9

Related Questions