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!