A typical idiom for processing a regular expression-matched substring using java.regex.Matcher is:
Pattern pattern = Pattern.compile("(cola)+");
Matcher matcher = pattern.matcher("cola, cola, I love cola.");
while (mather.find()) {
// do something with the current match.
System.err.println(matcher.group());
}
If you just want to do read-only processing for the matched part, you should be able to write it as stream processing. Like this.
Matcher matcher = pattern.matcher("cola, cola, I love cola.");
matcher.forEach(h -> System.err.println(h.group()); //h is something that represents a match (needs to be defined)
It was good to think that it could be realized by creating an implementation of java.util.stream.Stream that wraps Matcher, but it is difficult to implement because there are too many interfaces and methods.
https://docs.oracle.com/javase/jp/9/docs/api/java/util/stream/Stream.html
Is there an easy way to implement Stream?
MatcherThe original article listed the general solutions below, but for Matcher you can get the complete answer by usingMatcher # results ()from Java 9. The implementation of this method implements exactly what I wrote above.
Pattern pattern = Pattern.compile("(cola)+");
pattern.matcher("cola, cola, I love cola.").results()
.forEach(x -> System.err.println(x.group()));
NOTE: Thank you to @ saka1029 for pointing this out.
Please refer to the following for the general method of iterating something other than Matcher.
As a result of a little research, it was found that the following can be written by combining StreamSupport # stream and Spliterators # spliteratorUnknownSize.
As you can see, this method can be applied not only to Matcher but also to the implementation of java.util.Iterator.
That's why it's so versatile that I'll make a note of it.
[Addition: I understand that this example alone is longer and more complicated than the original code :-)]
RegExTest.java
import java.util.Iterator;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
/**
*
*/
public class RegExTest {
/**
* @param args
*/
public static void main(String[] args) throws Exception {
final Pattern pattern = Pattern.compile("(cola)+");
final Stream<Matcher> s = StreamSupport.stream(
Spliterators.spliteratorUnknownSize(
new Iterator<Matcher>() {
final Matcher matcher = pattern.matcher("cola, cola, I love cola.");
@Override
public boolean hasNext() {
return matcher.find();
}
@Override
public Matcher next() {
return matcher;
}
},
Spliterator.NONNULL | Spliterator.IMMUTABLE),
false);
//You can now use it in the same way as the example at the beginning!
s.forEach(m -> System.err.println(m.group()));
}
}
java.util.Iterator@ saka1029 pointed out again, the method Stream # iterate provided by Java9 of java.util.stream.Stream. Using api / java / util / stream / Stream.html # iterate (T, java.util.function.Predicate, java.util.function.UnaryOperator)), it is beautiful without implementing ʻIterator` as shown below. I learned that I can write in. Thank you, @ saka1029. I'm glad that Java9 provided this new way of writing, because there would have been many people other than me who wished I could write it like this.
final Pattern pattern = Pattern.compile("(cola)+");
Stream.iterate(pattern.matcher("cola, cola, I love cola."), m -> m.find(), m -> m)
.forEach(m -> System.out.println(m.group()));
Recommended Posts