1. Function interface revisited.

  • Java: backwards compatible: do not break existing code with new features.

  • Way forward: enhancements to the collection framework.

    • Extending interfaces without breaking implementations

      • add default functions

      • add static helper functions example: compare java 7 and java 8 Comparator. 1 The Java 7 version has two abstract methods, which were the only kind in Java before 8. 2 The Java 8 version has one abstract method, making it into a functional interface, 7 default and 8 static methods whose functionality is now available to every class implementing Comparator.

Have a look yourselves: Java 7 Comparator and Java 8 Comparator

The concept of functional interfaces or single abstract method is the secret ingredient to let the compiler guess the appropriate shape of the function that matches a lambda expression.

2. <S.H.A.P.E.> of java.util.functions.

The java.util.functions, which is introduced in Java 8 only contains functional interfaces and nothing else. The class contains the most common shapes of functions that may occur in lambda expressions. You can see that all reference type functional interfaces heavily rely on generics. The use of the proper generics is essential for functional interfaces to function properly.

We will use the notation <input type> → <result type> for the shape of a Functional interface. Note that the shape is determined by the one (abstract) method of the functional interface. The style used in java.util.function is somewhat mnemonic in choosing the generic type parameters in the type interface type definition.

  • T as only parameter, either a input or output e.g. Supplier<T>

  • T for input R for Result e.g. Function<T,R>

  • T and U for input, R for Result

  • T, U for input, R for result and X for exception in throws clause of the method.


  • Function<T,R>: shape <T> → <R> also known as mapping function, from one type to another.

  • BiFunction<T,U,R>: shape <T,U> → <R>.

  • Consumer<T>: shape <T> → () black hole? Eats Ts in any case.

  • Supplier<T> : shape () → <T> also source of T-objects.

Specialized functions for primitive types:

  • e.g. ToDoubleBiFunction<T,U>: shape <T,U> → double producing a double from two arguments.

  • LongConsumer: shape long →() munges longs to make them disappear. :-)

The package documentation makes an interesting read.

Exceptions in Lambda expressions need special consideration. In particular check exceptions actually counteract the conciseness of lambda expression. In those cases, where the lambda expression or reference method throws an exception, that exceptions is commonly wrapped in an unchecked exception, e.g. UncheckedIOException to wrap an IOException. UncheckedIOException has been introduced in Java 8 for just that purpose.

If you need to declare a functional interface throwing an exception, the following is a way to do that:

throwing functional interface
interface FunctionThrowing<T,R,<X extends Throwable>> {
    R apply(U u) throws X;

Shape wise it looks like <T,U> → R | X pronounced as from t,u to either R or a thrown exception.