javajava-streampredicate

Apply Pattern#asMatchPredicate with Stream#takeWhile results in compilation error


I try to apply a Predicate from a Pattern to a Stream of String values:

final var someString = "first\nsecond\nthird"
final var myPattern  = java.util.regex.Pattern.compile("second");
final var sb         = new java.lang.StringBuilder();

someString.lines()
  .takeWhile(not(myPattern::asMatchPredicate))
  .forEachOrdered(sb::append)
  ;

But the compiler refuses this with the error:

method asMatchPredicate in class java.util.regex.Pattern cannot be applied to given types
 required: no arguments
 found: java.lang.String
 reason: actual and formal argument lists differ in length

But why? The predicate takes a String (Predicate<String>) and the takeWhile method expects a Predicate<? extends String>.


Solution

  • Effectively you're doing the following:

    Predicate<String> predicate = myMatcher::asMatchPredicate;
    

    The method reference means you're trying to implement your own Predicate<String> instead of using the one returned by Pattern#asMatchPredicate(). That cannot work in this case for two reasons:

    1. The Pattern#asMatchPredicate() method accepts no arguments, but the Predicate#test(T) method accepts a single argument.
    2. The Pattern#asMatchPredicate() method returns a Predicate<String>, but the Predicate#test(T) method returns a boolean.

    Since the Pattern#asMatchPredicate() method already returns a Predicate<String> there's no reason to use a method reference here—just negate the returned value. In other words, you could do either:

    .takeWhile(Predicate.not(myMatcher.asMatchPredicate()))
    

    Or:

    .takeWhile(myMatcher.asMatchPredicate().negate())