Consumer, Supplier, Predicate and Function of Java 8

Posted by kristolklp on Mon, 29 Nov 2021 20:49:20 +0100

Today, we will talk about the usage of the interfaces of Consumer, Supplier, predict and Function. In the usage of Java 8, although these interfaces are not used blatantly, they are silent. Why do you say that?

These interfaces are   java.util.function   Under the package are Consumer, supplier, predicate and function. I believe 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 specific application scenarios!

1. Consumer interface

We can see from the literal meaning that the consumer interface is a consumer interface. It is so simple to pass in parameters and then output values. Some methods in Java 8 look very abstract. In fact, as long as you understand it, you feel it is easy to use and very simple.

Let's take a look at an example, and then analyze the interface.

1.1 Consumer instance

   /**
     * consumer Interface test
     */
    @Test
    public void test_Consumer() {
        //① use consumer Interface implementation method
        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("********************");

        //② use lambda expression, forEach What the method needs is one Consumer Interface
        stream = Stream.of("aaa", "bbb", "ddd", "ccc", "fff");
        Consumer<String> consumer1 = (s) -> System.out.println(s);//lambda The expression returns a Consumer Interface
        stream.forEach(consumer1);
        //More direct way
        //stream.forEach((s) -> System.out.println(s));
        System.out.println("********************");

        //③ Use method references, which are also a consumer
        stream = Stream.of("aaa", "bbb", "ddd", "ccc", "fff");
        Consumer consumer2 = System.out::println;
        stream.forEach(consumer);
        //More direct way
        //stream.forEach(System.out::println);
    }

Output results

1.2 case analysis

①   consumer interface analysis

In code ①, we create it directly   Consumer   Interface, and implements a   accept   This method is the key to this interface.

Let's have a look   accept   method; This method passes in a parameter and does not return a value. When we found out   forEach   Need one   Consumer   When a parameter of type is passed in, the corresponding value can be output.

② lambda expression as consumer

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

In the above code, we use the following   lambda   Expression as   Consumer. Take a closer look and you'll find that lambda   The return value of an expression is a   Consumer; So you can understand why   forEach   Methods can use lamdda expressions as arguments.

③ Method reference as consumer

Consumer consumer2 = System.out::println;

In the above code, we use a method reference as a Consumer, which can also be passed to   forEach   method.

1.3 other Consumer interfaces

In addition to the above Consumer interfaces, 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 reading the above examples, we can summarize them as follows.

① Consumer is an interface and only implements one   accept   Method, you can output information as a "consumer".
② In fact, the return values of lambda expressions and method references are   Consumer types, so they can act as   forEach   Method and outputs a value.

2 Supplier interface

The Supplier interface is a supply interface. In fact, it is a container that can be used to store data and then be used by other methods. Do you understand it very well? If you still don't understand it, take a look at the following examples and you will understand it completely!

2.1 Supplier instance

    /**
     * Supplier For interface testing, the supplier is equivalent to a container or variable that can store values
     */
    @Test
    public void test_Supplier() {
        //① use Supplier Interface implementation method,only one get Method, no parameters, returns a value
        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("********************");

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

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

Output results

2.2 case analysis

① Supplier interface analysis

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

Take a look at this code. We implement a Supplier object by creating a Supplier object   get   Method, which has no parameters and returns a value; Therefore, every time you use this interface, a value will be returned and saved in this interface, so it is a container.

② lambda expression as Supplier

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

The above code, we use   The lambda expression returns an interface of type Supplier, and then we call   get   Method to get this value.

③ Method reference as Supplier

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

Method reference is also an interface that returns a Supplier type.

2.3 Supplier instance 2

After we read the first example, we should have an understanding. Let's take another look.

    /**
     * Supplier Interface test 2: use the interface method that requires Supplier
     */
    @Test
    public void test_Supplier2() {
        Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5);
        //Return a optional object
        Optional<Integer> first = stream.filter(i -> i > 4)
                .findFirst();

        //optional Object needs Supplier Interface method
        //orElse,If first If there is a number in, this number is returned. If it does not exist, the incoming number is returned
        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 first If there is a number in, this number is returned. If it does not exist, it is returned supplier Returned value
        System.out.println(first.orElseGet(supplier));
    }

Output results

code analysis

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

Use this method to obtain an Optional object. Then, the orElse method and orElseGet in the Optional object need a Supplier interface.

//optional Object needs Supplier Interface method
        //orElse,If first If there is a number in, this number is returned. If it does not exist, the incoming number is returned
        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 first If there is a number in, this number is returned. If it does not exist, it is returned supplier Returned value
        System.out.println(first.orElseGet(supplier));
  • orElse: if there is a number in the first, this number will be returned. If it does not exist, the passed in number will be put back
  • orElseGet: returns the number if it exists in the first. If it does not exist, returns the value returned by the 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 Boolean supplier are used in the same way as above.

2.5 Supplier summary

① The Supplier interface can be understood as a container for storing data.
② The Supplier interface has a   get   Method to return a value.

3 predict interface

The Predicate interface is a Predicate interface. In fact, it is a judgment interface similar to bool type. We'll see later.

3.1 predict instance

  /**
     * Predicate Predicate test, predicate is actually a judgment, similar to bool
     */
    @Test
    public void test_Predicate() {
        //① use Predicate Interface implementation method,only one test Method, pass in a parameter and return 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("********************");

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

    }

Output results

3.2 case analysis

① Predict interface analysis

//① use Predicate Interface implementation method,only one test Method, pass in a parameter and return 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, where the implementation class   test   Method, you need to pass in a parameter and return a   bool   Value, so the function of this interface is to judge!

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

Look again, call the test method, pass in a value, and a bool value will be returned.

② Use a lambda expression as a predicate

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

lambda expressions return a   Predicate   Interface, then call   test   method!

3.3 predict interface instance 2

    /**
     * Predicate Predicate test, and predicate is used as an interface
     */
    @Test
    public void test_Predicate2() {
        //① take Predicate As filter Interface, Predicate Play a role of 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, and then implements it   test   Method, make a judgment in the test method: if the passed in parameter 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   of   filter   Method, filter   The parameter required by the method is the predict interface, so here as long as the data greater than 5 will be output.

3.4 predict interface summary

① Predicate is a predicate interface. In fact, it only plays a judgment role.
② Predicate implements a   test   Method to make judgment.

4 Function interface

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

4.1 Function interface instance

    /**
     * Function Test function is used to convert one value to another
     */
    @Test
    public void test_Function() {
        //① use map Method, the first parameter of the generic type 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

//① use map Method, the first parameter of the generic type 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, which implements a   apply   Method, which has an input parameter and an output parameter. Among them, the first parameter of generic type 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 then return the length of each string as a return value.

② Important application map method

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

stay   Function   The important application of interface has to be said   Stream   Class   map   Method, map   Method passes in a   Function   Interface to return a converted   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. the use method is the same as above.

4.4 Function interface summary

① Function interface is a functional interface, which is used to convert data.
② Function interface implementation   apply   Method to do the conversion.

5 Summary

Through the previous introduction, I have a detailed understanding of the interfaces of Consumer, Supplier, predict and Function. In fact, these interfaces are not very difficult, but a little abstract. If you understand them more, you will find them very simple and easy to use!

Topics: Java