What is lambda? and why do we need it?

When I started coding GUI application using Java, I realized my code was cluttered with too many anonymous classes. Each time, I had to handle an event the inlined implementation of ActionListener introduced nested and unreadable lines of code. How many of you have written code like below

signUpUserBtn.addActionListener(new ActionListener(){
  public void actionPerformed(ActionEvent e){
    someDelegate.handleUserSignUp(data);
  }
});

Or maybe something like the creation of the thread

Thread t = new Thread(new Runnable(){
  public void run(){
    performSomeActivityOnNewThread();
  }
});

In most of the cases, it was just one line statement to delegate the flow or perform certain computation and return the value. But prior to Java 8, there was no convenient way compact this code. The other option was to create dedicated Class and instantiate it wherever required. But this approach is not suitable as there was no shared functionality. Each implementation required different methods to be invoked or objects to be referenced. While languages like Lisp, Erlang had a nice feature called Lambda to write concise code, Java didn’t improve much until version 8 was released.

Lambda and Functional Interface (SAM)
In functional programming languages, Lambda is treated as a function, which can be passed around. Lambda expressions make code readable and concise. In Java since everything is an object, Lambda expression represents a specific type. More precisely, Lambda expression represents an implementation of a Functional Interface (Interface with one single abstract method). Hene it is necessary to have a good understanding of Functional Interface before proceeding with Lamda.

Lambda function consists of parameter definition and logic that is expressed in body, with an arrow operator that sits between them.

parameters -> expression

Refer to following additional characteristics that apply to Lambda expression

  • Optional Type Declaration While declaring parameters for lambda expression, declaration of type is optional. The type of parameters is inferred by the compiler based on type of value. Hence (Runnable r, Integer timeout) becomes (r, timeout)
  • Optional brackets When a single parameter is required for method, round brackets can be completely avoided. Hence (param) becomes param
  • Optional curly braces If there is only single statement in the body expression, curly brackets are not required. It is required only when there are multiple statements.
  • Optional Return statement Also a return keyword can be avoided if there is single expression. Hence (a, b) -> { return a+b; } can be coded as (a,b)-> {a+b;}

While we have learnt a lot about Lambda, Let’s have a look at some of the examples to understand it better. Lets have a look at the code for ActionLister again.

signUpUserBtn.addActionListener(new ActionListener(){
  public void actionPerformed(ActionEvent e){
    someDelegate.handleUserSignUp(data);
  }
});

With Lambda expression, it can be easily changed to

signUpUserBtn.addActionListener( e -> someDelegate.handleUserSignUp(data));

Does that look much better and readable? Note that any variable you refer inside Lambda expression must be final or effectively final OR else compiler will generate error. Let’s have a look at how Thread can be implemented. So before Lambda expression, it looks something like this

Thread t = new Thread(new Runnable(){
  public void run(){
    performSomeActivityOnNewThread();
  }
});

With Lambda expression,

Thread t = new Thread(()->performSomeActivityOnNewthread());

How about sorting a list of students based on a name? In Java 7 or before, we will have to

  1. Create an implementation of Comparator either inline or dedicated class.
  2. Implemente compare(object1, object2) method.
  3. Write logic to compare name

With Java 8 Lambda, it can be

Collections.sort(studentList, (s1,s2)-> s1.compareTo(s2));

Isn’t that whole lot better, than the pseudo steps we just defined? You may have noticed by now, how much efforts Lambda can save in typing the code and also it makes it very concise. As said earlier, Lambda expressions can be easily be passed around.

Runnable r = ()-> System.out.println("I can be executed with Thread");

someMethodWithThread(new Thread(r));

But that’s not all, with Java 8 Streams API, Lambda expression also enable parallel processing of collections. We will discuss that in the next article for Streams API. Till then, keep practising Lambda.

Be Sociable, Share!

Leave a Comment.