Java 9
Cleaner code could be achieved with overloaded in Java 9 method from Matcher class:
public String replaceAll(Function<MatchResult,String> replacer)
. Basically we can now replace code like
StringBuffer sb = new StringBuffer();
while(matcher.find()){
matcher.appendReplacement(sb, /*create replacement*/);
}
matcher.appendTail(sb);
String result = sb.toString;
with
String replaced = matcher.replaceAll(match -> /*create replacement*/);
For example
String replaced = Pattern.compile("\\b\\w")
.matcher("foo bar baz")
.replaceAll(match -> match.group().toUpperCase());
//replaced: "Foo Bar Baz"
There was also added support for stream of elements matching pattern: public Stream<MatchResult> results()
, but IMO your loop doesn't look like good candidate for streams. Even with results()
your code would look like:
//BTW Java 9 provides support for StringBuilder beside StringBuffer
//for appendReplacement/appendTail
Matcher matcher = ...
StringBuilder buf = new StringBuilder();
matcher.results()
.map(result -> String.valueOf((char) Integer.parseInt(result.group(1))) )
.forEach(replacement -> matcher.appendReplacement(buf, replacement));
matcher.appendTail(buf);
String decodeString = buf.toString();
so it doesn't look much cleaner.
Java 8
In Java 8 Pattern and Matcher classes didn't change much in terms of stream support. Only Pattern received public Stream<String> splitAsStream(CharSequence input)
method, but it creates stream of elements where pattern represents delimiter on which we want to split, not text which we want to find.
If you want to simplify your code in Java 8, write your own method in which you will supply Matcher and function which will map matched content (preferably represented by MatchResult or Matcher so it could access group(...)
methods) to replacement which should be put instead of it.
Such method could look like:
public static String replaceMatches(Matcher m, Function<MatchResult, String> mapping){
StringBuffer sb = new StringBuffer();
while(m.find()){
MatchResult matchResult = m.toMatchResult();
m.appendReplacement(sb, mapping.apply(matchResult));
}
m.appendTail(sb);
return sb.toString();
}
and you could use it like:
Pattern p = Pattern.compile("\\b\\w");
Matcher m = p.matcher("foo bar baz");
String result = replaceMatches(m, mr -> mr.group().toUpperCase());
System.out.println(result);
Result: Foo Bar Baz
.