java.util.function package in Java 8.

Reading Time: 4 minutes

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

Functional interfaces provide target types for lambda expressions and method references. Each functional interface has a single abstract method, called the functional method for that functional interface.

java.util.function-logo

Any interface with a SAM(Single Abstract Method) is a functional interface, and its implementation may be treated as lambda expressions.

Java 8’s default methods are not abstract and do not count; a functional interface may still have multiple default methods.

java.util.function package contains lots of functional interfaces. Some of them are as follows:

Function<T, R> :

The Function Interface is a part of the java.util.function package.

Where an object of a particular type is the input, an operation is performed on it and object of another type is returned as output, the in-built functional interface Function<T,R> can be used without defining a new functional interface.

Represents a function that accepts one argument and produces a result. Hence this functional interface takes in 2 generics namely as follows:

  • T: denotes the type of the input argument
  • R: denotes the return type of the function

for example:

public class FindLength {
    public static void main(String[] args) {
        String name = "Aasif";
        /**
         * Implementation of functional interface.
         */
        Function<String, Integer> strLength = str-> str.length();
        System.out.println("Length of name is "+strLength.apply(name));
    }
}

We may replace the lambda with a method reference that matches passed and returned value types for example:

public class FindLength {
    public static void main(String[] args) {
        /**
         * using method reference.
         */
        Function<String, Integer> getAge = String::length;
        Integer lengthOfPhone = getAge.apply("83940545");
        System.out.println("Length of phone :"+lengthOfPhone);
    }
}

BiFunction<T, U, R>

It is similar to the Function interface but It accepts two arguments and produces a result.

  • T: denotes the type of the first argument
  • U: denotes the type of the second argument
  • R: denotes the return type of the function

The main advantage of using a BiFunction<T, U, R> is that it allows us to use two input arguments while in Function<T, R> we can only have 1 input argument.

for example:

public class BiFunctionExample {
    public static void main(String[] args) {
//       BiFunction to add two numbers and get the result as string
        BiFunction<Integer, Integer, String> add =
                (num1, num2) -> "Sum : " + (num1 + num2);
        System.out.println(add.apply(5, 3));
    }
}

Consumer<T>

The Consumer Interface is a part of the java.util.function package. Represents an operation that accepts a single input argument and returns nothing.

  • T: denotes the type of the input argument

It contains one abstract method namely accept() that accepts one value and performs the operation on the given argument. It also contains one default method.

Consumer can be used in all contexts where an object needs to be consumed, for instance taken as input, operation is to be performed without returning any result.

for example:

public class _Consumer {
    public static void main(String[] args) {
        // Consumer to print something
        Consumer<String> print = obj-> System.out.println(obj);
        print.accept("Nice to see you");
    }
}

Another example to print name of the courses using forEach() method that accepts Consumer.

public class _Consumer {
    public static void main(String[] args) {
        List<String> courses = Arrays.asList(
                "Java","Python","C++","PHP","JavaScript");
        courses.stream().forEach(System.out::println);
    }
}

A simple example of andThen() method in Consumer.

public class _Consumer {
    public static void main(String[] args) {
//        define a list of courses name
        List<String> courses = Arrays.asList(
                "Java", "Python", "C++", "PHP", "JavaScript");
//        implementing a consumer
        Consumer<String> printName = name -> System.out.print("Printed: ");
//        implement a consumer to use for andThen() method.
        Consumer<String> printNameWithAndThen =
                printName.andThen(name -> System.out.println(name));
//        define a foreach loop to use both the consumers.
        for (String name: courses) {
            printNameWithAndThen.accept(name);
        }
    }
}

BiConsumer<T>

Represents an operation that accepts two input arguments and returns nothing.  It is similar to Consumer interface but it takes two arguments instead of one.

for example:

public class _BiConsumer {
    public static void main(String[] args) {
//        BiConsumer to add two numbers
        BiConsumer<Integer,Integer> add =
                (num1, num2) -> System.out.println("Sum: "+(num1+num2));
        add.accept(4,9);
    }
}

Predicate<T>

The Predicate Interface is a part of the java.util.function package. Represents a predicate (boolean-valued function) of one argument.

A function that accepts one argument and generates a boolean value as an answer is known as a predicate. A predicate functional interface of java is a type of function which accepts a single value or argument and does processing on it, and returns a boolean. 

  • T: denotes the type of the input to the predicate

test(T t) is the abstract method which define the signature of the lambda expression or method reference which can be assigned to a target of type Predicate.

Predicate also contains three default methods are and() , or() and negate() which enable us to do various types of boolean operations.

for example:

public class BiFunctionExample {
    public static void main(String[] args) {
        /**
         *  Predicate to validate a number.
         */
        Predicate<String> isValid = phone-> {
            if(phone.startsWith("+91")){
                return true;
            }
            return false;
        };
        System.out.println("Phone is valid: "+isValid.test("+918654789652"));
    }
}

BiPredicate<T, V>

BiPredicate is a functional interface similar to Predicate, but it takes two arguments for the test instead of one. It returns a boolean.

It also contains the same default methods as Predicate.

public class _BiPredicate {
    public static void main(String[] args) {
//        BiPredicate to check a phone number valid or not.
        BiPredicate<String, String> isValid = 
                (phone, country) -> {
            if (country.equals("India") 
                    && phone.startsWith("+91")) {
                return true;
            }
            return false;
        };
//        using test() of BiPredicate to validate a number.
        boolean phone = isValid.test("+918394024565", "India");
        System.out.println("Phone is valid: " + phone);
    }
}

Supplier<T>

Represents a supplier of results.

Basically It represents a function that does’t take any argument and returns a result of type T.

  • T: denotes the type of the result

It does not contains default methods. get() method is the primary abstract method of the Supplier functional interface. 

Suppliers are useful when we don’t need to supply any value and obtain a result at the same time.

example:

public class _Supplier {
    enum gender{
        FEMALE,
        MALE
    }
    public static void main(String[] args) {
//        Supplier to get return a gender
        Supplier<String> getGender =
                ()-> "Gender is " + gender.MALE;
        System.out.println(getGender.get());
    }
}

Another example of Supplier to get database connection url.

public class _Supplier {
    public static void main(String[] args) {
//        Supplier to get dbUrl
        Supplier<String> getDatabaseConnectionUrl =
                () -> "jdbc:mysql://localhost:3306/studentsdb";
//        getting dbUrl
        String dbUrl = getDatabaseConnectionUrl.get();
        System.out.println("Database Connection Url: "+dbUrl);
    }
}

Written by 

Aasif Ali is a Software Consultant at Knoldus Inc. He has done Post Graduation from Quantum University Roorkee. He has the knowledge of various programming languages. He is passionate about Java development and curious to learn Java Technologies. He is always impatient and enthusiastic to learn new things. He is a quick learner, problem solver and always enjoy to help others. His hobbies are watching Sci-fi movies , Playing badminton and listening to songs.