Given following list of Strings:
List<String> progLangs = Arrays.asList("c#", "java", "python", "scala");
and a regex Pattern that should match 4-letter lowercase string.
Pattern p = Pattern.compile("[a-z]{4}");
Now I want to find elements of progLangs
that fit to the Pattern p
.
Doing it the old way:
for (String lang : progLangs) {
if (p.matcher(lang).matches()) {
System.out.println(lang);
}
}
I get the expected result:
java
But when I try to achieve the same with Java 8 stream and transform the pattern to a predicate using Pattern.asPredicate:
progLangs.stream()
.filter(p.asPredicate())
.forEach(System.out::println);
the result is:
java
python
scala
Why is it so? It seems that Patter.asPredicate produces a predicate that accepts partial matches. What is the equivalent in the Pattern API? The documentation says only:
Creates a predicate which can be used to match a string.
I would expect it to be the typical Pattern.matcher(String).matches()
but it's something else... How to explain this inconsistency?
With JDK/11, you can use the new Pattern.asMatchPredicate
API to accomplish what you were initially trying to, in a one-liner as :
progLangs.stream()
.filter(p.asMatchPredicate()) // the matches predicate
.forEach(System.out::println);
Here is what the javadoc for the same reads :
/**
* Creates a predicate that tests if this pattern matches a given input string.
*
* @apiNote
* This method creates a predicate that behaves as if it creates a matcher
* from the input sequence and then calls matches, for example a
* predicate of the form:
* s -> matcher(s).matches();
*
* @return The predicate which can be used for matching an input string
* against this pattern.
* @since 11
* @see Matcher#matches
*/
public Predicate<String> asMatchPredicate() {
return s -> matcher(s).matches();
}
They are not doing the same thing - the Predicate uses find
rather than matches
. The equivalent 'old code' way would be:
for (String lang : progLangs) {
if (p.matcher(lang).find()) {
System.out.println(lang);
}
}
In this case I would use my own predicate:
progLangs.stream()
.filter(s -> p.matcher(s).matches())
.forEach(System.out::println);
The documentation does seem misleading though.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With