Sunday, 13 November 2016

Common Functional interfaces introduced in Java 8

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
 If you are using JDK 8 in your IDE do check out these classes. You can also find all these in oracle documentation -
 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.

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.

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.
These functional interfaces are summarized below -

Summary


Related Links 


t> UA-39527780-1 back to top