Difference between Predicate<T> and Function<T, R>
First and foremost a Predicate<T> is strictly a boolean-valued function:
_ _ _ _ _ _ _
| |
T --> | predicate | --> boolean
|_ _ _ _ _ _ _|
Whereas this is not necessarily true for a Function<T, R>:
_ _ _ _ _ _ _
| |
T --> | function | --> R
|_ _ _ _ _ _ _|
The latter consumes any type of object just as Predicate<T> enables but can vary in the return type.
Use case of Predicate<T> and Function<T, R>
The use case for Predicate<T> is when you require a function that consumes one argument of type T and returns a boolean. e.g. that may be in a situation where you want to filter a stream of elements, find the first element from a stream that satisfies a condition as such of .filter(predicate).findFirst(), or checking the presence of an element from a stream that satisfies a certain condition as such of anyMatch, noneMatch, allMatch etc.
The use case for Function<T, R> is when you require a function that consumes one argument of type T and transforms that into a type R e.g. that may be when calling stream.map(func).
Explanation of your code snippet:
In regards to the example snippet in your post Predicate<String> and Function<String, Boolean> are the same thing in terms of what they represent i.e. they both represent a function taking a String and returning a boolean. However, the former avoids boxing the returned value from boolean to Boolean whereas the latter does not.
That said, this does not necessarily mean wherever you can use a Predicate<String> you can also use a Function<String, Boolean> or vice versa.
Example:
While this compiles:
Predicate<String> predicate = p -> p.length() == 21;
Stream<String> stream = stringList().stream().filter(predicate);
This does not:
Function<String, Boolean> function = p -> p.length() == 21;
Stream<String> stream = stringList().stream().filter(function);
and vice versa:
While this works:
Function<String, Boolean> function = p -> p.length() == 21;
Stream<Boolean> stream = stringList().stream().map(function);
This does not:
Predicate<String> predicate = p -> p.length() == 21;
Stream<Boolean> stream = stringList().stream().map(predicate);