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
?
Matcher
The 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