简体   繁体   中英

replaceAll for StringBuilder with regex support?

I've looked in the Java API and some common 3rd party libraries but I'm unable to find a suitable method that will do what String.replaceAll does, except for StringBuilder.

I know that with a little work, it can be done for StringBuffer, but I don't want to go down this road because StringBuffer is slower.

Does anyone know of any 3rd party utilies, or if there is a quick piece of code to implement this functionality?

String.replaceAll is just a convenience method for Matcher.replaceAll . Matcher is the "actual" way to use regex in Java and is allows for a lot more sophisticated use cases.

Moreover, anything that can be done with regex methods on String can be done with similar methods on a Matcher . The beauty is, that Matcher s work with more than just String s: Matcher s can be obtained for any CharSequence (an interface, which is implemented by StringBuilder , StringBuffer , String and CharBuffer ). So you can simply do:

import java.util.regex.*;

...

StringBuilder sb = new StringBuilder();
sb.append("This works with StringBuffers");
Pattern p = Pattern.compile("\\Buffer\\B");
Matcher m = p.matcher(sb);
System.out.println(m.replaceAll("uilder"));

Will output This works with StringBuilders .

Working demo.

Regex does not modify a mutable CharSequence internally. Regex parses a CharSequence to return a String , where String is the result. StringBuffer is an exception as there is special handling - as for StringBuilder being CharSequence , you have to modify it with a match result.

What you can do instead:

// Class
private static final Pattern MY_PATTERN = Pattern.compile("my|regex");

{ // Method
    StringBuilder builder;
    // ...

    Matcher m = MY_PATTERN.matcher(builder);
    builder.replace(0, builder.length(), m.replaceAll("<b>$0</b>"));
}

View a test code demo!

I don't want to go down this road because StringBuffer is slower.

True, but with the usual premature optimization caveat, and more importantly, modern JVMs use escape analysis to remove the StringBuffer/Vector/HashTable locks in certain cases, so once that optimization happens, the performance will be roughly the same.

Apache Harmony Matcher source code seems fully reworkable to be used with StringBuilder instead of the currently used StringBuffer , just move to the different package. It seems not dragging a lot of dependences with it. Apache license that is at the start of the file may not be bad even for commercial project.

GNU Classpath code can also be reused but the license is more difficult there (you need to publish your changed version of the Matcher but probably not the rest of your code). Same about the original Sun's implementation that can be found here in the OpenJDK project.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM