Sunday, October 2, 2016

Java 8 Lambda Expressions - The What and Why

Introduction

Java 8 has lot of new interesting features. Lambda expression is one of them. This feature is not something very new. Microsoft DotNet already had this feature in v3.0. Dynamic languages like Javascript, Scala, Ruby are all already having this feature. We could say Lambda expressions are simplified form of anonymous methods.

In this post I would like to discuss about what is Lambda expression, why do we need this.

Why do we need Lambda Expression in Java?

Why are we interested in this feature after so long time? Lets take below example for our discussion. When we create GUI in Java using AWT package we deal with three main components, Event Source, Event and Event Handler.

AWT Event Handling Components, Event Source, Event and Event Handler
Java AWT Event Handling

In the above GUI we have a simple button 'OK' as 'Event Source'. Whenever we perform some action on the event source we actually generate 'Event' and it is passed to another component called 'Event Handler'. 

The Event Handler is the important component for our discussion. It is a set of instruction/behavior we want to run at the time of receiving an event. In other words event handler is a set of code we want to run at a later point of time in response to an event.

It looks straightforward and simple, but in Java we can't pass set of code instructions directly to another part of the program for later execution. In our example we can't directly associate the event handler code to the event source for later execution whenever there is an event generated from the event source. 

How we handle this in Java is explained in the below image.


Java way of associating code for later execution in Object oriented way
Java way of associating code for later execution

As Java is Object oriented language, we handle everything in terms of objects. Hence, we wrap this event handler code into a method (public void actionPerformed(ActionEvent e){ }), then add this method to an Object (ActionListener type) and then add/register this Object to the event source for later execution. 

Now, when an event is generated from the Event Source the registered EventListener object is notified and it executes the associated method(s).

We write the below code in Java to do the same above.

Associating the Event Handler to the Event Source using btn.addActionListener()
Associating the Event Handler to the Event Source in Java

Here,
  • We create an instance of type ActionListener interface which has one abstract method (event handler method) called
 public void actionPerformed(ActionEvent e)
  • Register this instance to the Event Source ('OK' button) by using the code
btnOk.addActionListener(instance of ActionListener)
The important point to note here is the way we create instance of ActionListener interface. There is no class implementing ActionListener interface. We just use Anonymous Inner class. This Anonymous inner class helps avoid creating separate implementation classes and saves coding time.

But, there are few concerns with the usage of Anonymous Inner classes. We can consider two of them.
  1. At run time a separate instance is created for each Anonymous inner class definition. Even if the same definition is repeated multiple times the run time creates multiple instances for each anonymous inner class definition. This wastes the memory as well as adds overhead to the garbage collection process.
  2. If you have another Event Source and want to handle events for that source then you may need to add one more set of similar code as above. This leads to have more boiler plate code as mentioned in the below image.

Redundant Event Handler code. new ActionListner() { public void actionPerformed(){}}
Boiler plate Event Handler code

So, what we are going to do here is to just remove these boiler plate code and you will get the below as remaining.

Anonymous Method, without method name-just has param and body
Anonymous Method

Here, we just kept the method parameter(s) and the method body. Such type of structure is called as Anonymous Method. We have removed the instance type as well as method name. 

In other words we leave/register the anonymous method to the event source for later execution. Please recollect what we had mentioned in the beginning that we had registered anonymous class to the event source. 

Fine, now when an event is generated the Event object will be assigned to the param 'e'  and will be passed to the method body. The method body now will be executed and will return the result. You can now understand the usage of the arrow which takes the parameter(s) and passing to the method body.

The working example code is available in Java 8 Lambda Examples. Please run TestLambda.java.

What is Lambda Expression in Java?

So, we moved from anonymous class to anonymous method in Java 8. We can take another example of creating a thread using Runnable interface. We can follow the same here and is explained in the below image.

Java 8 helps replacing anonymous class with anonymous method
Moving from Anonymous Class to Method

The anonymous method is nothing but the simple expression as discussed above.
(ActionEvent e) --> { ----};
() --> System.out.println("Inner Thread"); 
These expressions are called as Lambda Expressions in Java.

The first expression can be rewritten without specifying the parameter type as below.
e --> { System.out.println("button is clicked!")}; (parentheses can be removed as there is only one param)
e --> System.out.println("button is clicked!"); (the curly braces can be removed as there is only one statement within the body) 
Similarly if there is another event source btnCancel then we can write the expression as below.
e --> System.out.println("button is clicked!")
The lambda expression can be assigned to a variable for later reuse and using it in a declarative way.

ActionListener btnListener = e -> System.out.println(“button is clicked!”);
btnOk.addActionListener(btnListener);
btnCancel.addActionListener(btnListener);

The important point to note here is that Lambda Expression works only with an Interface with only one abstract method. Such type of interface is called a Functional interface in Java 8. Hence, ActionListener and Runnable interfaces which we discussed are functional interfaces. There are many functional interfaces added in Java 8 in the package java.util.function. You can spend some time going thro' this package and get familiar with all the new functional interfaces and their methods.

Summary

Based on the above discussion we can understand the need of Lambda Expression in Java as below.

summary-why do we need lambda
Summary

Hope you enjoyed the post. Welcome your comments!


5 comments:

  1. I think lambda break the concept of OOP, especially affecting the relationship between the behavior defined in the class and the behavior of the object, instance of the class. I can understand in scripting languages, as well as in languages not strongly typed but not in java that was a strongly typed language.

    ReplyDelete
  2. So finally, garbage collector will take some rest...

    ReplyDelete
  3. Understandable article by giving simple examples. Thanks.

    ReplyDelete

Do you know - Series - 4: Boxing and Unboxing - Integer assignment and comparison

We know about boxing and unboxing in Java. It is about automatic conversion of primitive type value into its Wrapper Object equivalent type...