Getting functional with Java 8
06 Feb 2017Java 8 provides developers with functional programming facilities that are very new to the language itself.
In today’s post, I’ll go through a primer of the different facilities that you can use.
Functional Interfaces
Single abstract method interfaces have been taken a step further in Java 8, where the programmer is able to decorate their interface using a @FunctionalInterface annotation. These can then be represented as lambda expressions and method references. These are building blocks for functional programming.
Consumer<T>
Represents an operation that accepts a single input argument and returns no result. Unlike most other functional interfaces, Consumer is expected to operate via side-effects.
Uses are passing to the forEach function.
Supplier<T>
This is a functional interface and can therefore be used as the assignment target for a lambda expression or method reference.
Used in the creation of streams.
Predicate<T>
This is a functional interface and can therefore be used as the assignment target for a lambda expression or method reference.
Used with filter
Function<T, R>
This is a functional interface and can therefore be used as the assignment target for a lambda expression or method reference.
Used to pass to map
Functional Syntax
Defining a Functional Interface
@FunctionalInterface
public interface TailCall<T> {
TailCall<T> apply();
default boolean isComplete() { return false; }
}
A functional interface must:
- Have one abstract, unimplemented method
- May have zero or more default or implemented methods
- May have static methods
Lambda expressions
// no parameters
() -> func(1)
// explicit definition of parameter types
(final String colour) -> System.out.println(colour)
// implicit parameter definition
(colour) -> System.out.println(colour)
colour -> System.out.println(colour)
// multiples
(x, y) -> x * y
// multi-line lambda
(x) -> {
func1(x);
func2(x);
}
Composition, method references
products.stream()
.filter(Pricing::hasDiscount)
.mapToDouble(Product::getUnitPrice)
.average()
.getAsDouble();