Java 8 Lambda Expressions – A Quick Revision




Anonymous - Image Credit: Pixabay

Can you remember anonymous classes?
What did we actually do with an anonymous class?

Here’s an example. I think you can still remember Java swing. It is used to create graphical user interfaces with Java.
In swing, we have button objects. When a user clicks on a button, some work has to be done. This work is passed to the button via an object implementing ActionListener interface. For that , we use an anonymous class.

ActionListener interface has only one function called actionPerformed().

When user clicks the button, the code inside that function will be executed.

OK. Now, why are we writing

part?

If you look close enough, you’ll see we need only the function!!!!

Name of the function is also not necessary, because, actionPerformed() is the only method in the interface ActionListener.

So, our useful code part will always be:

Well, now you can remove all the unnecessary parts in our code using a Lambda expression…

Let’s use it.

Only one line. How cool is that? This is a Lambda expression.

Let’s see how to use Lambdas 🙂

Lambda expressions?

In the previous example, first we instantiated an anonymous class to describe the functionality of a button. That is, to show how the button works.

But the code of an anonymous class is bit indirect and verbose. With Java 8 lambda expressions, we can directly pass the functionality as an argument.
It’s just an anonymous FUNCTION!

Lambda expressions are used in the context of a functional interface.

Functional Interface

Interface having only ONE abstract method is called a functional interface. For example, in the ActionListener interface above, we have only one method, actionPerformed().

So, when we are creating an object implementing only a functional interface, we don’t need to write long anonymous class thing again. We can use a lambda!

Annotation

If you are creating your own functional interface, you can use the annotation @FunctionalInterface before the declaration. It will show an error if you include more than one method to your interface.

Eg:

Parts of a Lambda expression

 

Parts of a Lambda Expression

If you passing multiple lines, use brackets {}

In your functional interface, if the declared method only returns something, you don’t need to type return.

For example if your functional interface is

and you can create an object implementing Filter like this

You have to return boolean value when implementing the test() method.

str.isEmpty() method returns a true or false value and you don’t need to explicitly write the “return” keyword when your method has only one line.

If you have multiple lines, then you can use {}. But if you use brackets, you have to include return statement.

Point to be noted:

Java can detect the type of of the variable str in the (String str) above. How? Because, in the functional interface declaration, we have only ONE method.
In that only method, we are writing the type of the parameter. Here, the type is String. So, it knows str is String.

So, you can just write,

You can remove the brackets in (str) as well.

(Later in this article, you’ll see this example lambda expression can be replaced with a method reference as well.

)

Functional Interface examples

You can of course create your own functional interface and use lambda expressions for their implementation.

But, there are some common functional interfaces that are already available in java.util.function package.

I’ll describe 2 of them here as examples. The rest, you can easily find details by an online search 🙂

Predicate interface

You can import this interface using

This Predicate example requires the knowledge of behaviour parameterization that I have already discussed in the previous article. For now, Let’s have a quick revision with an example.

Predicate functional interface has a method called test() that accepts an object T and returns a boolean value.

The interface is:

Suppose you have an created a class called Book. It is as follows;

It has several variables for various things in a book: Name, category, author and the edition. They are private variables and therefore, get and set methods are needed to be written.

Also, the Book Class has the toString() method so that when we want to print a Book variable by calling print() function, a string containing the name, edition and the author of the book is shown.

Now, suppose we have a list of books. We now need to traverse book list and put all electronics books in to a new list.

We can use a for loop to do that.

See, in the filter(), we use a Predicate that accepts an object of type Book and the test() method in predicate should return a boolean value whether the book is in category “Electronics” or not.

How do we call the filter() method?

We have the unfiltered ArrayList of books called rawList.

the part

is the one which implements the Predicate interface.

The behaviour parameterization is achieved with this interface. We can easily change the Predicate code and pass the new behaviour to the same filter() method.

Then a filtered book list with a different requirement can be obtained. But, if you write the behaviour of filtering electronics books inside the for loop like old days 🙂 then you have to create another new method to get a different filtered book list.

(With Java8 Streams, we even don’t need to write a filter() method with the for loop.  Streams has its own filter() method. Then, we can shrink all code we written for filter() and its call to

I hope to discuss about Java Streams in next articles)

Consumer interface

This interface consists of an abstract method called accept() that takes an object of type T and returns null.

This is useful when performing an operation on the object T.

For example, suppose we want to do something with each book in book list. For that, we can write a method as follows.

Now, I want to print each book. So I can give,

(The Book object will give a meaningful output for print() method, because, in the Book class, we have overridden the toString() method in the Book class definition above)

Method references

1. Calling static methods

Sometimes, you use a Lambda expression only to call a method. For example, in the previous example of forEach() method, you are using the lambda only to call print() function. So, you can write,

instead of

that is, you can replace the lambda,

with

Note the structure of this method reference,

Class_name::Method_name

we are calling a method inside the accept() method of the Consumer object.

For the accept() method, we are passing an argument called book which is of type Book.

That same book is used as an argument to another method.

In that case, we don’t need to create the argument book in the first place.

Java can understand you have to input an argument and the same object is used for again as an argument for the method you are going to call.

The method print() is a static one. You can have method references for non static methods as well.

2. Calling non-static methods

The format of the method reference for calling instance method of an object is

Class_name::Instance_method_name

For example, say, you have created a functional interface having a method that takes a book object and gives out the author.

So the lambda expression would be

Now you can do the same thing. The method reference would be

3. calling non-static method of an existing object

If you are referring an instance method of an existing object, the method reference would be

Existing_object_name::Method_name

Eg:
Suppose you have a Book object created locally. You have written a functional interface like this.

Now, you have a local Book object in your main() method, called book.

You also need an object implementing the functional interface. So you can write,

instead of the lambda expression,

A plenty of articles explaining java lambdas are available in the internet. But, when I searched to learn about the Lambda expressions, I couldn’t find myself a satisfactory result with a quick approach. So, I note down some key points and wrote this article 🙂 If you find any problem, error or anything, please be kind to comment. I really appreciate that!

If you like the post, I request kindly to share it with your friends and support the blog. Thanks for reading!