What is the basic syntax for lambda expressions? How are lambda expressions related to anonymous classes? What parts of a lambda expression can be omitted?
- [Instructor] Hi, welcome to the second section of this course. This section is going to be about lambda expressions. In particular, we're going to see how to write your first lambda expression. Then we're going to consider typing issues related to lambda expressions. Then we're going to see how lambda expressions can access values from the surrounding context, and finally, we're going to introduce another new feature called method references.
Let's start with the first video of this section on writing your first lambda expression. In this video, we're going to see how lambda expressions can be seen as a more compact alternative to anonymous classes. Then, we're going to find out that you can get an even more compact syntax by removing parameter types, removing parentheses around the parameter list, and even removing curly braces around the body of your lambda expression.
Now you cannot always do these things, but most of the time, you can. Let's start with our first example of the syntax of lambda expressions. So first of all, lambda expressions are a compact syntax to implement functional interfaces. In this example, we're going to implement the Comparator interface. So as we've seen in previous videos, Comparator is a standard functional interface in the Java API. It's used to define objects that can compare other objects.
In this case, we're going to define a Comparator between strings that compares them based on their length, and as you can see, the syntax is very simple. It's just a list of parameters, similar to a parameter list of a method. In this case it's two strings. Then there's an arrow which is actually obtained by a dash and a greater than symbol, one next to the other, followed by the body of the lambda expression, which in this case, returns a comparison between the lengths of the two strings.
Now let's switch to a more complex example. Okay, so in this example, we're going to create a couple of comparators between employees. So if you missed this in the previous videos, let me just quickly remind you that Employee is a very simple class that we use for our examples. It contains two fields called name and salary, and it just contains a very straightforward constructor and the usual getters and setters for these two fields.
Let's go back to our example. So as I said, we're going to create a couple of comparators and all these comparators will be functionally equivalent; they will all compare two employees based on their names. So it's going to be an alphabetic or lexicographic comparison between two names. So first, here on line 10 to 14, let's define this comparator in the old-fashioned way using an anonymous class.
So as you probably know, the anonymous class syntax requires us to write new, then the interface name, and then provide the full body of this class, of this anonymous class, which is implementing the comparator interface. So in particular, we have to write down the full abstract method that we are implementing. In this case, it's called compare. It takes two Employees as arguments and it returns an integer.
Here instead we do the same thing with less code using a lambda expression. So in this case, we don't have to write, we don't have to use the new keyword, we don't have to repeat the interface name, and we don't even have to write the name of the abstract method that we're implementing. We're just writing the parameter list, arrow body of the abstract method. So this is why this feature only works for functional interfaces, because functional interfaces have a single abstract method so there is no ambiguity here as to which abstract method we're implementing.
There's only one, it's called Compare, so we don't have to specify that. We just have to write down the body of the method itself. Let's do one more step and be even more succinct by omitting the parameter types. So we don't have to specify that they're employees. We just write a comma b, and the compiler is going to figure out that these two are actually employees because we are assigning this expression, this lambda expression to a comparator of Employee.
Finally, in this case, since the body of our lambda expression contained a single statement, and this statement is a return statement, we can remove both the curly braces and the return keyword and just have, after the arrow, the expression that we want to return. And that's where lambda expressions actually get their name from. They get their name from the fact that their body can be a single expression that is automatically returned.
As a side note, notice that you cannot just remove braces and leave the return keyword in because that's going to be a compile time error. In all this, the lambda expression takes two parameters. Let's see some other scenarios. For instance, let's consider a lambda expression with no parameters. To do this, consider the Runnable interface. As you probably know, this is a standard Java interface which is used in multi-threading to specify the behavior of threads, and this interface has a single abstract method, so it's a functional interface.
This method is called run and it takes no arguments. So if we want to implement it with a lambda expression, you can just write an empty list of parameters, so empty parentheses, and then the body, and then you can pass this object to a thread, to the constructor of Thread. Actually, you can also combine these two lines in a single line, and just pass to the constructor of Thread the lambda expression by itself and this will work just as well, and notice that in this new version, in this line, we didn't even have to mention the Runnable interface.
The compiler is going to figure out that this constructor is expecting a Runnable object; therefore, this lambda expression is implementing Runnable, and so this function body here is the function body for the run method, and actually once again, since this is a single statement, we can do without braces. Finally, there is another special case. It's lambda expressions with a single parameter.
For instance, consider the functional interface Consumer that we briefly presented in a previous video. So this functional interface has a single abstract method called Accept and this Accept method has a single argument. In this case, we're going to take a string and print its length, and since it's a single argument, we can do without the parentheses around the argument itself. We cannot type it; we just have to write down its name, then the arrow and the body of the lambda expression.
Let's quickly summarize what we've learned. We've learned the basic syntax for lambda expressions. It's parameters, arrow, body, where parameters can be a couple of things such as a pair of typed parameters or untyped parameters, a single untyped parameter, or even an empty list of parameters, and also, if we have a single parameter, this can also appear with no type and no parentheses around it. On the other hand, the body can be either a block of code of a single expression.
That's all for this video. Let's move on to the next one on typing lambda expressions.
Note: To get the best results from this course, you should be familiar with basic Java programming concepts, including lists, maps, and sets, and have a suitable IDE, such as Eclipse, NetBeans, or IntelliJ.
This course was created and produced by Packt Publishing. We are honored to host this training in our library.
- What is functional programming?
- What are functional interfaces?
- Writing lambda expressions
- Creating functional interfaces
- Composing functions
- Sequential data processing with streams
- Using parallel streams