You don't understand lambda expressions yet, do you?

1. What is Lambda?

We know that for a Java variable, we can assign it a "value".

What if you want to assign a "block of code" to a Java variable? For example, assign the code on the right to a Java variable called aBlockOfCode:

Before Java 8, this was not possible. But after Java 8, it can be done by using the Lambda feature, as shown in the figure:

Of course, this is not a very concise way of writing. So, to make this assignment more concise, we can remove some useless declarations like this:

In this way, we have succeeded in assigning "a piece of code" to a variable very elegantly. And "this piece of code", or "this function assigned to a variable", is a Lambda expression. But there is still a question here, what should be the type of the variable aBlockOfCode?

In Java 8, all lambda types are an interface, and the lambda expression itself, that is, "that piece of code", needs to be an implementation of this interface. This is a key to understanding Lambda, in short, a Lambda expression itself is an implementation of an interface. For easy understanding, keep reading. Add a type to the above aBlockOfCode:

This kind of interface type that only one interface function needs to be implemented, we call it "functional interface". In order to avoid later people adding interface functions to this interface, resulting in multiple interface functions that need to be implemented, becoming a "non-functional interface", we can add a declaration @FunctionalInterface to this, so that others cannot add it in it New interface functions:

In this way, you get a complete lambda expression declaration:

2. What is the role of lambda expressions?

The most intuitive effect is to make the code extremely concise.

We can compare Lambda expressions and traditional Java implementations of the same interface:

The two notations are essentially equivalent. But obviously, the way of writing in Java 8 is more elegant and concise. Moreover, since Lambda can be directly assigned to a variable, we can directly pass Lambda as a parameter to the function, while traditional Java must have a clear definition of the interface implementation and initialization:

In some cases, this interface implementation only needs to be used once. The traditional Java 7 must require you to define a "pollution environment" interface to implement MyInterfaceImpl, while Java 8's Lambda is much cleaner.

Example 1:

Lambda combined with FunctionalInterface Lib, forEach, stream(), method reference and other new features can make the code more concise!

Assuming both the definition of Person and the value of List<Person> are given:

Now you need to print out the FirstName of all the people whose LastName starts with "Z" in the GuiltyPersons List.

Original Lambda writing method: define two functional interfaces, define a static function, call the static function and assign a Lambda expression to the parameter.

This code is actually more concise, but can we be more concise?

sure. In Java 8 there is a functional interface package that defines a large number of possible functional interfaces (java.util.function (Java Platform SE 8 )). Therefore, we don't need to define the two functional interfaces of NameChecker and Executor at all here, we can directly use Predicate<T> and Consumer<T> in the Java 8 functional interface package - because they are a pair of The interface definition is actually the same as NameChecker/Executor.

The first simplification - use the functional interface package:

The for each loop in the static function is actually very annoying. Here you can use the forEach() that comes with Iterable instead. forEach() itself can accept a Consumer<T> parameter.

Second simplification - replace the foreach loop with Iterable.forEach():

Since the static function is actually just a pass operation on the List, here we can get rid of the static function and directly use the stream() feature to complete it. Several methods of stream() accept parameters such as Predicate<T>, Consumer<T> (java.util.stream (Java Platform SE 8 )). You understand the above content, stream() is very easy to understand here, and no more explanation is needed.

Step 3 Simplification - Use stream() instead of static functions:

Compared with the original Lambda writing method, it is very, very concise here. But if we ask to change it to print all the information of the person, and p -> System.out.println(p); Then we can use the Method reference to continue to simplify. The so-called Method reference is to replace the Lambda expression with the method of other Object/Class that has been written. The format is as follows:

Step 4 Simplification - In case of println(p), you can use Method reference instead of lambda expression in forEach:

This is basically the most concise version that can be written.

Example 2:

Lambda and Optional<T> can make Java's handling of null extremely elegant

Suppose we have a person object, and an Optional wrapper for the person object:

If Optional<T> is not used in conjunction with Lambda, it will not make the original tedious null check simple.

Only when Optional<T> is used in conjunction with Lambda, its true power can be exerted!

Let's now compare the following four common null handling differences between Java 8's Lambda+Optional<T> and traditional Java.

Situation 1 - Dry if it exists

Case 2 - return if exists, return fart if not

Case 3 - Return if it exists, if not generated by the function

Case 4 - Deadly Serial Null Check

As can be clearly seen from the above four cases, Optional<T>+Lambda can save us writing a lot of ifElse blocks. Especially for the deadly serial null check in case 4, the traditional java writing method is tedious and difficult to understand, while the new Optional<T>+Lambda is fresh and refined, clear and concise.

Related Posts