Introduction to Consumer, Supplier, Predicate and Function in Java 8

Today we will also talk about the usage of Consumer, Supplier, Predicate, Function interfaces. In the usage of Java 8, these interfaces, although not explicitly used, are quiet and moisturizing. Why do you say that?

These interfaces are all in the java.util.function package. They are Consumer, supplier, predicate and function. I believe that with the following explanation, you should be very clear about the function of this interface.

Now, let's talk about the usage of this interface from a specific application scenario.

1 Consumer interface

Literally, we can see that the consumer interface is a consumer interface. By passing in parameters and then outputting values, it is so simple. Some methods of Java 8 seem abstract. In fact, as long as you understand them, they feel very useful and very simple.

Let's start with an example and then analyze the interface.

1.1 Consumer Example

/**
     * consumer Interface testing
     */
    @Test
    public void test_Consumer() {
        //1. Implementing Method with consumer Interface
        Consumer<String> consumer = new Consumer<String>() {

            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        };
        Stream<String> stream = Stream.of("aaa", "bbb", "ddd", "ccc", "fff");
        stream.forEach(consumer);

        System.out.println("********************");

        //(2) Using lambda expression, forEach method needs a Consumer interface.
        stream = Stream.of("aaa", "bbb", "ddd", "ccc", "fff");
        Consumer<String> consumer1 = (s) -> System.out.println(s);//The lambda expression returns a Consumer interface
        stream.forEach(consumer1);
        //A more direct approach
        //stream.forEach((s) -> System.out.println(s));
        System.out.println("********************");

        //(3) Use method reference, method reference is also a consumer.
        stream = Stream.of("aaa", "bbb", "ddd", "ccc", "fff");
        Consumer consumer2 = System.out::println;
        stream.forEach(consumer);
        //A more direct approach
        //stream.forEach(System.out::println);
    }

Output results

1.2 Example Analysis

(1) Analysis of consumer interface

In Code 1, we directly create the Consumer interface and implement a method called accept, which is the key to this interface.

Let's look at the accept method; this method passes in a parameter and does not return a value. When we find that forEach needs a Consumer type parameter, we can output the corresponding value after passing in.

(2) lambda expression as consumer

Consumer<String> consumer1 = (s) -> System.out.println(s);//The lambda expression returns a Consumer interface

In the code above, we use the following lambda expression as Consumer. If you look closely, you will find that the return value of a lambda expression is a Consumer; therefore, you can also understand why the forEast method can use a lamdda expression as a parameter.

(3) Method citation as consumer

Consumer consumer2 = System.out::println;

In the code above, we use a method reference as a Consumer and can also pass it to the forEach method.

1.3 Other Consumer Interfaces

In addition to the Consumer interfaces used above, you can also use the following Consumer interfaces.
IntConsumer, DoubleConsumer, LongConsumer and BiConsumer are used in the same way as above.

1.4 Consumer Summary

After looking at the examples above, we can sum up several points.

Consumer is an interface, and as long as an accept method is implemented, it can output information as a "consumer".
(2) In fact, lambda expressions and method reference return values are Consumer types, so they can be used as parameters of forEast methods and output a value.

2 Supplier interface

Supplier interface is a supply-oriented interface, in fact, it is a container, which can be used to store data, and then other methods can use such an interface, is not very clear, if you still do not understand, look at the following examples, it must be thoroughly understood!

2.1 Supplier example

**
     * Supplier Interface testing, supplier Quite a container or variable that can store values
     */
    @Test
    public void test_Supplier() {
        //(1) Using the Supplier interface, there is only one get method, no parameters, and a value is returned.
        Supplier<Integer> supplier = new Supplier<Integer>() {
            @Override
            public Integer get() {
                //Returns a random value
                return new Random().nextInt();
            }
        };

        System.out.println(supplier.get());

        System.out.println("********************");

        //(2) Using lambda expression,
        supplier = () -> new Random().nextInt();
        System.out.println(supplier.get());
        System.out.println("********************");

        //(3) Use method quotation
        Supplier<Double> supplier2 = Math::random;
        System.out.println(supplier2.get());
    }

Output results

2.2 Example Analysis

1. Analysis of Supplier Interface

Supplier<Integer> supplier = new Supplier<Integer>() {
            @Override
            public Integer get() {
                //Returns a random value
                return new Random().nextInt();
            }
        };

Looking at this code, we implement a get method by creating a Supplier object, which returns a value without parameters; therefore, every time we use this interface, we return a value and save it in this interface, so it is a container.

lambda expression as Supplier

//(2) Using lambda expression,
        supplier = () -> new Random().nextInt();
        System.out.println(supplier.get());
        System.out.println("********************");

In the above code, we use lambda expression to return a Supplier-type interface, and then we call the get method to get the value.

(3) Method cited as Supplier

//(3) Use method quotation
        Supplier<Double> supplier2 = Math::random;
        System.out.println(supplier2.get());

Method references also return a Supplier-type interface.

2.3 Supplier instance 2

After we have looked at the first example, we should have an understanding. Let's look at another one.

/**
     * Supplier Interface test 2, using the interface method requiring Supplier
     */
    @Test
    public void test_Supplier2() {
        Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5);
        //Returns an optional object
        Optional<Integer> first = stream.filter(i -> i > 4)
                .findFirst();

        //Opti objects have methods that require Supplier interfaces
        //orElse, if there is a number in first, it returns that number, and if not, it returns the number passed in.
        System.out.println(first.orElse(1));
        System.out.println(first.orElse(7));

        System.out.println("********************");

        Supplier<Integer> supplier = new Supplier<Integer>() {
            @Override
            public Integer get() {
                //Returns a random value
                return new Random().nextInt();
            }
        };

        //orElseGet, if there is a number in first, returns this number, if not, returns the value returned by supplier
        System.out.println(first.orElseGet(supplier));
    }

Output results

code analysis

Optional<Integer> first = stream.filter(i -> i > 4)
                .findFirst();

Use this method to get an Optional object, and then, in the Optional object, there is an orElse method and orElseGet that require a Supplier interface.

//Opti objects have methods that require Supplier interfaces
        //orElse, if there is a number in first, it returns that number, and if not, it returns the number passed in.
        System.out.println(first.orElse(1));
        System.out.println(first.orElse(7));

        System.out.println("********************");

        Supplier<Integer> supplier = new Supplier<Integer>() {
            @Override
            public Integer get() {
                //Returns a random value
                return new Random().nextInt();
            }
        };

        //orElseGet, if there is a number in first, returns this number, if not, returns the value returned by supplier
        System.out.println(first.orElseGet(supplier));
  • orElse: If there is a number in first, return that number, and if there is no, return the incoming number.
  • orElseGet: If there is a number in first, it returns that number. If not, it returns the value returned by supplier.

2.4 Other Supplier Interfaces

In addition to the Supplier interfaces used above, you can also use the following Supplier interfaces.
IntSupplier, DoubleSupplier, LongSupplier and BooleanSupplier are used in the same way as above.

2.5 Supplier Summary

The Supplier interface can be understood as a container for loading data.
(2) The Supplier interface has a get method that returns values.

3 Predicate interface

The Predicate interface is a predicate interface. In fact, it's a bool-like judgment interface, as you can see later.

3.1 Predicate instance

/**
     * Predicate In predicate testing, a predicate is actually a judgment function similar to bool's.
     */
    @Test
    public void test_Predicate() {
        //(1) Using the Predicate interface, there is only one test method, passing in a parameter and returning a bool value.
        Predicate<Integer> predicate = new Predicate<Integer>() {
            @Override
            public boolean test(Integer integer) {
                if(integer > 5){
                    return true;
                }
                return false;
            }
        };

        System.out.println(predicate.test(6));

        System.out.println("********************");

        //(2) Using lambda expression,
        predicate = (t) -> t > 5;
        System.out.println(predicate.test(1));
        System.out.println("********************");

    }

Output results

3.2 Example Analysis

Predicate interface analysis

//(1) Using the Predicate interface, there is only one test method, passing in a parameter and returning a bool value.
        Predicate<Integer> predicate = new Predicate<Integer>() {
            @Override
            public boolean test(Integer integer) {
                if(integer > 5){
                    return true;
                }
                return false;
            }
        };

In this code, a Predicate interface object is created, in which the implementation of class test method requires passing in a parameter and returning a bool value, so the function of this interface is to judge!

System.out.println(predicate.test(6));

Next, call the test method, pass in a value, and return a bool value.

(2) Using lambda expression as predicate

//(2) Using lambda expression,
        predicate = (t) -> t > 5;
        System.out.println(predicate.test(1));
        System.out.println("********************");

The lambda expression returns a Predicate interface and then calls the test method!

3.3 Predicate interface instance 2

/**
     * Predicate Predicate is used as an interface for predicate testing
     */
    @Test
    public void test_Predicate2() {
        //Predicate serves as a filter interface, and Predicate serves as a judgment.
        Predicate<Integer> predicate = new Predicate<Integer>() {
            @Override
            public boolean test(Integer integer) {
                if(integer > 5){
                    return true;
                }
                return false;
            }
        };

        Stream<Integer> stream = Stream.of(1, 23, 3, 4, 5, 56, 6, 6);
        List<Integer> list = stream.filter(predicate).collect(Collectors.toList());
        list.forEach(System.out::println);

        System.out.println("********************");

    }

Output results

This code first creates a Predicate object, then implements the test method, and makes a judgment in the test method: if the parameter passed in is greater than 5, it returns true, otherwise it returns false;

Stream<Integer> stream = Stream.of(1, 23, 3, 4, 5, 56, 6, 6);
        List<Integer> list = stream.filter(predicate).collect(Collectors.toList());
        list.forEach(System.out::println);

This code calls Stream's filter method, which requires the Predicate interface as a parameter, so data greater than 5 will be output here.

3.4 Summary of Predicate Interface

Predicate is a predicate interface, but in fact it only serves as a judgment.
Predicate judges by implementing a test method.

4 Function Interface

Function interface is a functional interface. One of its functions is to transform input data into output data in another form.

4.1 Function Interface Example

/**
     * Function In testing, function is used to convert one value to another.
     */
    @Test
    public void test_Function() {
        //(1) Using map method, the first parameter of generics is the type before conversion and the second is the type after conversion.
        Function<String, Integer> function = new Function<String, Integer>() {
            @Override
            public Integer apply(String s) {
                return s.length();//Gets the length of each string and returns
            }
        };

        Stream<String> stream = Stream.of("aaa", "bbbbb", "ccccccv");
        Stream<Integer> stream1 = stream.map(function);
        stream1.forEach(System.out::println);

        System.out.println("********************");

    }

Output results

4.2 Code Analysis

Function Interface Analysis

//(1) Using map method, the first parameter of generics is the type before conversion and the second is the type after conversion.
        Function<String, Integer> function = new Function<String, Integer>() {
            @Override
            public Integer apply(String s) {
                return s.length();//Gets the length of each string and returns
            }
        };

This code creates a Function interface object and implements an application method, which has an input parameter and an output parameter. Among them, the first parameter of generics is the type before conversion, and the second is the type after conversion.

In the above code, you get the length of the string and return the length of each string as a return value.

(2) Important application of map method

 Stream<String> stream = Stream.of("aaa", "bbbbb", "ccccccv");
        Stream<Integer> stream1 = stream.map(function);
        stream1.forEach(System.out::println);

In the important application of Function interface, we have to say Stream class map method. The map method passes into a Function interface and returns a transformed Stream class.

4.3 Other Function Interfaces

In addition to the Function interfaces used above, you can also use the following Function interfaces.
IntFunction, DoubleFunction, LongFunction, ToIntFunction, ToDoubleFunction, DoubleToIntFunction, etc. are used in the same way as above.

4.4 Function Interface Summary

Function interface is a functional interface and a function of data conversion.
(2) Function interface implements application method to do conversion.

5 Summary

Through the previous introduction, we have a detailed understanding of the Conumer, Supplier, Predicate, Function interfaces, in fact, these interfaces are not difficult, but a little abstract, more understanding will find it very simple, and particularly useful!

If you like Wechat reading, you can also pay attention to my Wechat public number: learn java well, and get high quality learning resources.

Keywords: Java Lambda

Added by clapton on Fri, 02 Aug 2019 09:05:36 +0300