Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Predicate from Function Reference (of boolean type)

I need to compose a stream operation with a predicate based on a boolean function. Found a workaround via rethrowing a method's argument as a predicate, as shown:

public <T> Predicate<T> pred(final Predicate<T> aLambda) {
    return aLambda;
}

public List<String> foo() {
    return new ArrayList<String>().stream() //of course, this does nothing, simplified
            .filter(pred(String::isEmpty).negate())
            .collect(Collectors.toList());
}

The 'pred' method seems to do nothing, however not this:

public List<String> foo() {
    return new ArrayList<String>().stream() 
            .filter((String::isEmpty).negate()) 
            .collect(Collectors.toList());
}

nor any in-line conversion:

public List<String> foo() {
    return new ArrayList<String>().stream() 
            .filter(((Predicate)String::isEmpty).negate())
            .collect(Collectors.toList());
}

seems to work. Fails with the error

The target type of this expression must be a functional interface

What the fancy conversion happens in the 'pred(...)' method?

like image 420
Tomas F. Avatar asked Jan 30 '18 14:01

Tomas F.


People also ask

What is a boolean predicate?

Retrieves rows where the value of an expression is true, false, or unknown (null).

Does a predicate return boolean?

Generally predicate means a statement that determines whether a value could be true or false. In programming predicates mean functions with one argument that return a boolean value.

What is the function of the predicate?

Predicate functions are functions that return a single TRUE or FALSE . You use predicate functions to check if your input meets some condition. For example, is. character() is a predicate function that returns TRUE if its input is of type character and FALSE otherwise.

How predicate is a functional interface?

Functional Interface: This is a functional interface and can therefore be used as the assignment target for a lambda expression or method reference. Represents a predicate (boolean-valued function) of one argument. This is a functional interface whose functional method is test(Object) .


2 Answers

You could write a utility method:

class PredicateUtils {

    public static <T> Predicate<T> not(Predicate<T> predicate) {
        return predicate.negate();
    }

}

and use it as follows:

.filter(not(String::isEmpty))

I believe it's more readable than casting to a Predicate<T>:

.filter(((Predicate<String>)String::isEmpty).negate())

Though I would go with a simple lambda:

s -> !s.isEmpty()

What the fancy conversion happens in the pred(...) method?

You have specified a context - the type to work with. For instance, a String::isEmpty could be a Function<String, Boolean>, or Predicate<String>, or my @FunctionalInterface, or something else.

You clearly said that you were expecting a Predicate<T>, and you would return an instance of the Predicate<T>. The compiler is now able to figure out what the type you want to use.

like image 195
Andrew Tobilko Avatar answered Oct 05 '22 07:10

Andrew Tobilko


You can use

((Predicate<String>) String::isEmpty).negate()

(note the use of the proper generic type)

or (preferred):

s -> !s.isEmpty()

which is way simpler and readable.

like image 28
JB Nizet Avatar answered Oct 05 '22 08:10

JB Nizet