JB Header
Java 8 java.util.function package tutorial
Introduction This tutorial explains the newly introduced package in Java 8 java.util.function. It first explains the purpose of this package, followed by the contexts in which the functional interfaces defined in this package can be used and finally gives an overview of the most important functional interfaces that this package contains.
Note - Before reading this tutorial it is important that the reader understands the concepts of functional interfaces(tutorial here Click to Read tutorial on Java 8 Functional Interfaces) and lambda expressions(tutorial here Click to Read Java 8 Lambda Expressions tutorial). Purpose of java.util.function package For common use cases where a lambda expression or a method referenceClick to read tutorial on Method References is needed, these are generally assigned to a target type of a Functional Interface which has its function descriptorTutorial on function descriptors( abstract method's signature in terms of parameter & return types) which should match the signature of the lambda expression.

java.util.function package provides a set of re-usable common functional interfaces( and their corresponding lambda) definitions which can be used by the programmer in his code instead of creating brand new functional interfaces.

For example, when we need to check for a condition and return a boolean value the function descriptor would be (T)->boolean where T is the parameter to the abstract method/lambda and boolean is the return value. Now, wherever we need to use a lambda with the (T)->boolean descriptor, we can use the in-built java.util.function.Predicate<T> functional interface because the descriptor for Predicate<T>’s function is also (T)->boolean. Then in our code we can write a method which accepts this functional interface like this -
public void doSomething(Object someObject,Predicate<T> predicateInstance){
//doSomething method's code goes here 
}
Where -
  • doSomething() method uses the instance of Predicate<T> for some calculations on someObject.
  • This someObject will be a variable or a collection of type T so that this predicateInstance which is also of type T can be applied to someObject. By applied I mean that some attribute of T can be tested and a boolean value returned as per the descriptor - (T)->boolean.
And on the calling side the method doSomething() will be called like this -
doSomething(someObjectInstance, Integer i-> i>10)
Where -
  • The first parameter is of type someObject
  • Second parameter is a lambda expression
  • The lambda of second parameter has the same function descriptor as that of the Predicate<T> functional interface and hence can be passed as the second parameter
In the above example, a functional interface called Predicate<T>, which is in-built in java.util.function package, has been used by passing a lambda expression(Integer i-> i >10) which matches the function descriptor of the Predicate<T> interface. Similarly, method references, whose method signature matches a specific functional interface's function descriptor, can also be passed wherever expected target type is of that specific functional interface.

Like the above scenario where a functional interface with descriptor ‘(T)->boolean’ was expected, there are various other standard functional interface definitions required by programmers in their day-to-day coding, apart from their usage in java libraries. For all such common functional interface requirements Java has provided a set of commonly used functional interfaces through java.util.function package.

To sum up this section - java.util.function package provides standard library-based functional interface for common requirements as an alternative to creating brand new functional interfaces every time one is needed. Contexts in which Functional Interfaces can be assigned/used There are 3 ways\contexts in which functional interfaces are used as target types in code
  • Assignment context - This refers to cases where a lambda/method reference is assigned to the functional interface Predicate<T>’s instance -
    Predicate predicateToTest=(Integer integer -> integer > 10);
  • Method invocation context - This is when a lambda/method reference is passed to a method parameter which accepts the equivalent functional interface's instance -
    stream.filter(String::isEmpty)
  • Cast context - where a lambda/method reference of one type is explicitly typecast to a functional interface of another type -
    stream.map((ToIntFunction) e -> e.getSize())
4 fundamental and most commonly used functional interfaces Note - Each Functional Interface name in the table below links to individual tutorial for that interface.
Functional Interface Purpose
Consumer<T>Click to Read tutorial on Consumer<T> functional interface Represents an operation that accepts a single input argument and returns no result.
Function <T, R>Click to Read tutorial on Function<T, R> interface Represents a function that accepts one argument and produces a result.
Predicate<T> Click to Read tutorial on Predicate<T> functional interface Represents a predicate (boolean-valued function) of one argument.
Supplier<T> Click to Read tutorial on Supplier<T> functional interface Represents a supplier of results.