32

I know it may be a very basic question on SO but I want to know what is the difference between a Predicate and a Function Interface in Java8?

Predicate<String> predicateTest  = (s)-> s.length() > 5;       
System.out.println(predicateTest.test("Predicate"));

Function<String, Boolean> functionTest = str -> str.length()> 5;      
System.out.println(functionTest.apply("Function"));

Here in my Example both are returning true.The only thing is way of calling is different ?

NullPointer
  • 7,094
  • 5
  • 27
  • 41
  • 4
    A `Predicate` is just a `Function` that returns `Boolean`. Put another way `Predicate` is a `Function`. But `Predicate` returns a `boolean` so there is no inheritance relationship. – Boris the Spider Jul 20 '18 at 15:07
  • 4
    @BoristheSpider nitpick, it's `boolean` not `Boolean` – Eugene Jul 20 '18 at 15:08
  • @Eugene just tidying that up – Boris the Spider Jul 20 '18 at 15:08
  • 6
    Well, that’s a fundamental difference. A `Predicate` function may evaluate to `true` or `false` and nothing else. A `Function<…,Boolean>` may return `Boolean.TRUE`, `Boolean.FALSE`, [another `Boolean` instance](https://docs.oracle.com/javase/8/docs/api/java/lang/Boolean.html#Boolean-boolean-) representing either `true` or `false`, or `null`. – Holger Jul 20 '18 at 16:14

7 Answers7

44

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);
Ousmane D.
  • 54,915
  • 8
  • 91
  • 126
  • 3
    You could also mention that `Predicate` has default methods `and()`, `or()` and `negate()` which make sense for conditions, whereas the default methods on `Function` make more sense for filtering/chaining. – Jens Bannmann Jul 21 '18 at 07:25
  • @JensBannmann This is an important (practical!) point. Far more relevant than the handwaving babble in the other answers (which, when they say that there ~"is no difference", are basically just wrong...). Consider adding this as a (proper!) answer. Otherwise, I'd give it a try... – Marco13 Jul 21 '18 at 11:28
  • 1
    @JensBannmann Thanks for the feedback. I am not in a position to integrate that into my answer currently until later tonight but feel free to edit the answer and improve on it if need be. Alternatively, if you want you can also post your own answer as Marco suggests. :) – Ousmane D. Jul 21 '18 at 12:18
  • 1
    @Marco13 and Aominè: good idea, I turned it into [an answer](https://stackoverflow.com/a/51456996/7641). – Jens Bannmann Jul 21 '18 at 14:32
  • @Marco13 how in the world is that "wrong" when the OP says he only started with java-8? Of course you can go much into details here, I personally did not, on purpose – Eugene Jul 21 '18 at 18:01
  • 3
    @Eugene It's like someone creating a new `List` and a new `Set`, printing their `size()`, and then asking what's the difference. Of course, there is none: The size is `0` for both. Saying that *in this case* "there is no difference" may not be "wrong" (and I don't think that we have to argue about that), but it is misleading at the **very** least. In both cases, we are talking about different types with different methods, and I think that it is important to make clear what their differences are from a *usage* point of view. – Marco13 Jul 22 '18 at 12:54
8

in this case there is no difference, it matters only to the things you can apply to. So for example allMatch expects a Predicate, you can't pass a Function, even if logically they do the same thing.

Eugene
  • 117,005
  • 15
  • 201
  • 306
  • 3
    Using `myFunction::apply` would probably still work though – Lino Jul 20 '18 at 15:06
  • 1
    @Lino right, it would, but that would be a little extra on the behalf of the user – Eugene Jul 20 '18 at 15:07
  • 2
    Although this may not be the right place to "discuss" things (and if you want to, we can go into a chat). But in view of your comments on other answers, *this* answer may at least raise the question of why the different interfaces exist in the first place (and I think that's a good question, with some interesting technical quirks). So to speak, they could have omitted `Predicate`, and just expected a `Function` in methods like `anyMatch`. (Leaving the `null` issue aside for now). – Marco13 Jul 22 '18 at 13:00
  • @Marco13 no idea why, but IIRC initially it was `Block` for both `Predicate/Function`, I hope I remember correctly though – Eugene Jul 22 '18 at 19:56
5

There's really no difference.

In theory, there shouldn't be any functional difference between Predicate<T> and Function<T, Boolean>. A Predicate is just a function that takes an object of some type and returns a boolean. A Function is a generalization which can return any type, not just Boolean's.

There may be implementation details within Java itself that make them distinct, but they should be the same in theory.

An example would be if an interface could only accept a Predicate<String>, not a Function<String, Boolean.

  • 4
    This answer seems hypothetical rather than evidence based. There a lot of "in theory" "should" etc. Consider researching your answers better and providing evidence rather than speculation. – Boris the Spider Jul 20 '18 at 15:12
  • 1
    @BoristheSpider This isn't hypothetical. I'm not using "In Theory" to talk about things I don't understand, but rather what type theory itself would have to say about it. Java itself might implement it in a way that differs from the pure theory that these features are based on. – Nathaniel Pisarski Jul 23 '18 at 13:46
5

Aominè's answer covers the basic differences. I would like to add that the two interfaces also have different specialized default methods, i.e. methods you can call on any implementing class:

  • Predicate<T>
    • Predicate<T> and(Predicate<? super T> other) - Returns a composed predicate that represents a short-circuiting logical AND of this predicate and another.
    • Predicate<T> or(Predicate<? super T> other) - Returns a composed predicate that represents a short-circuiting logical OR of this predicate and another.
    • negate() - Returns a predicate that represents the logical negation of this predicate.
  • Function<T,R>
    • <V> Function<T,V> andThen(Function<? super R,? extends V> after) - Returns a composed function that first applies this function to its input, and then applies the after function to the result.
    • <V> Function<V,R> compose(Function<? super V,? extends T> before) - Returns a composed function that first applies the before function to its input, and then applies this function to the result.

As you can see, Predicate has useful methods for creating complex conditions, much like the operators you would use in a regular if statement, whereas Function has methods that support simple chaining.

Jens Bannmann
  • 4,845
  • 5
  • 49
  • 76
  • I have no idea how this matters, *of course* they have differrent methods, names and purposes. This is pulling the strings, to me – Eugene Jul 21 '18 at 18:10
4

Although it is an old post but I will summaries differences between them for newbies

Predicate: To implement conditional checks we should go for Predicate.

Function: To perform certain operations and to return some result we should go for function

Predicate: Predicate can take one type parameter which represents input type or argument type.

Function: Function can take 2 type parameters First one represents input type argument type and second one represents return type.

Predicate: Predicate defines one abstract function called test(). When using predicate you can say "test this condition" or "Testing this condition"

Function: Function defines one abstract function called apply(). When using function you can say "apply this function" or "applying this function"

Predicate: Always return boolean value.

Function: Function can return any type of value.

Sometimes people call predicate specail case of Function. Another difference between them is that they contain different type of default and static methods in their respective interfaces.

Umar Tahir
  • 585
  • 6
  • 21
2

A Predicate can only return a boolean (result of the test()) while Function does a transformation and can return anything (result of apply()).

A Predicate is used to test a condition.

A Function is used to do a transformation.

ACV
  • 9,964
  • 5
  • 76
  • 81
1

From a technical point of view, a Predicate<T> is just a function taking in a T and returning a boolean primitive result. However, from a usage point of view, a Predicate<T> is totally a different concept than a Function<T, Boolean>.

We use a Predicate<T> to perform a filter operation, in a stream pipeline for example, we take a Stream<T> of size n, filter it using a Predicate<T> to get a stream of size less than or equal to n. Meanwhile, a Function<T, Boolean> in a stream pipeline is used to perform a mapping operation to transform a Stream<T> into a Stream<Boolean>.

As you can see, Predicate<T> and a Function<T, Boolean> are technically the same (ignoring the wrapper Boolean for simplicity), but when put in a specific context (stream pipelines for example), it is totally a different story as each one of them plays a distinct role.

marsouf
  • 1,107
  • 8
  • 15