Background
In series of previous posts on Java 8 features we saw Lambda expressions and how to used them.
We saw basis of a Lambda expression is a functional interface. And then we saw a few functional interfaces as part of introduction to method references -
In this post well see some common functional interfaces that Java provides that you can use at your disposal.
Common Functional interfaces
A new package is introduced since Java 8 that holds all such common functional interfaces. This package is
- java.util.function
For now lets go over some commonly used functional interfaces from this package.
NOTE : The convention used here is generic type T for type parameter, for second type parameter the next letter U and for a distinct return type R is used as the generic type.
Predicate : Takes a single paramter of any type and returns a boolean [boolean test(T t)]
Predicate functional interface looks like -
@FunctionalInterface public interface Predicate<T> { /** * Evaluates this predicate on the given argument. * * @param t the input argument * @return {@code true} if the input argument matches the predicate, * otherwise {@code false} */ boolean test(T t); //other methods }
It accepts a parameter of type T and returns a boolean.
Note I have skipped other methods in the interface like default and static methods (Remember default methods and static methods do not affect the functional status of an interface)
Eg.
Output :
true
false
Note I have skipped other methods in the interface like default and static methods (Remember default methods and static methods do not affect the functional status of an interface)
Eg.
Predicate<String> emptyPredicate = x -> x.isEmpty(); System.out.println(emptyPredicate.test("")); System.out.println(emptyPredicate.test("abc"));
Output :
true
false
Consumer : Takes a single paramter of any type and has a void return type [void accept(T t)]
Consumer looks like below -
@FunctionalInterface public interface Consumer<T> { /** * Performs this operation on the given argument. * * @param t the input argument */ void accept(T t); }
It accepts an input parameter of type T and does does not return anything (has a void return type). It consumes the input.
Eg.
Consumer<String> printFunc = x -> System.out.println(x); printFunc.accept("Hello World!");
Output :
Hello World!
Supplier : Does not take any parameter and returns any type [ T get()]
Supplier looks like -
@FunctionalInterface public interface Supplier<T> { /** * Gets a result. * * @return a result */ T get(); }
Eg.
Supplier<String> strSupplier = () -> "SOME_CONSTANT"; System.out.println(strSupplier.get());
Output :
SOME_CONSTANT
I know that a lame example :) You can simple define and use a constant. Have used this to help you understand how it works. All constructor references in method references are essentially variants of supplier.
I know that a lame example :) You can simple define and use a constant. Have used this to help you understand how it works. All constructor references in method references are essentially variants of supplier.
UnaryOperator : Takes a single paramter of any type and returns of same type. [R apply(T t)]
UnaryOperator actually extends Function functional interface. Function looks like below -
public interface Function<T, R> { /** * Applies this function to the given argument. * * @param t the function argument * @return the function result */ R apply(T t); }
So as you see it take input parameter of type T and returns a parameter of type R. UnaryOperator is a special kind of Function where T and R are same. So it take input and returns output of same type.
Eg.
UnaryOperator<String> prefixOp = (name) -> "Mr. " + name; System.out.println(prefixOp.apply("Aniket"));
Output :
Mr. Aniket
That's some common functional interface. Now there are "Bi" versions of above interfaces that take in 2 inputs. For eg.
- BiConsumer<T, U> : Similar to Consumer<T> but takes two inputs of type T and consumes them i.e void return type.
- BiPredicate<T, U> : Similar to Predicate<T> but takes 2 inputs of type T and U and returns a boolean.
- BiFunction<T, U, R> : Similar to Function<T, R> but takes 2 inputs of type T and U and returns a parameter of type R.
- BinaryOperator<T> : Similar to UnaryOperator<T> but takes 2 parameters of type T and returns parameter of type T.
Summary
Related Links
- Using Lambda Expressions from Java 8(OSFG)
- Using Lambda expressions from Java 8 - Part 2(OSFG)
- Java 8 Method references and Lambda expression
- https://docs.oracle.com/javase/8/docs/api/java/util/function/package-summary.html
- Whats new in Java 8?(OSFG)