Skip to main content

Java Lambda Expression Explained with Example

Java 8 is one of most popular release in the history of Java and have introduced lots of major features like Lambda Expression, Method Reference, Stream API, new DateTime API, Default and static interface methods etc.. For complete list of new Java 8 feature read What’s New in JDK 8 article by oracle itself.

In this article, we are going to study Java Lambda Expression in details e.g. what is the lambda expression, why it so popular, what are the advantages of the lambda expression, what purpose is solved, how it differs from anonymous classes and why/how should we use it.
lambda expression logo

Why Java needs Lambda Expression

Java is a multiparadigm programming language (Supports Object Oriented, Imperative, Structured, Declarative style of programming). However, most of its design architecture is influenced by Object Oriented programming style.

And there are two variations of object-oriented programming (OOP) style
  • Class-based OOP style
  • Prototype-based OOP style → doesn’t support inheritance
Java supports class-based OOP style that’s why there should be a class for every object while JavaScript follows Prototype-based OOP style that’s why we don’t have the concept of class and inheritance in JavaScript. Everything in JavaScript is an object either it is a variable or a function while in Java a function (method) is state of the object.

Apart from this JavaScript also follows the Functional style of programming so we can assign functions to variables, pass functions as argument or return a function from other function etc..

Due to class-based nature of Java programming, it is hard to maintain functions as first class citizen similar as objects. That’s why Java does not support functional style of programming (before Java 8) and we can’t assign functions to variables or pass functions as argument or return them.

Lambda Expression is a way to introduce functional programming to Java. So by using lambda expression we can simply define and use functions wherever we need them (e.g. inside a method) without even creating objects. Due to lambda expression now functions have also become first class citizens in Java language.

What is Lambda Expression

By definition

A Lambda Expression is an anonymous function (a function defined, and possibly called, without being bound to an identifier and a name.

The concept is similar to anonymous classes or anonymous objects, Now we can declare methods wherever we want them without any name. The sole purpose of writing an anonymous class object is to override its method and provide our own functionality but for that single method, we always need to declare the class. With lambda expression, we can eliminate the declaration of the anonymous class and we can simply write the methods.

Since the old days of Swing, we always had written anonymous classes if we wanted to pass some functionality to any method. For example old event listener code and thread creation code look like

Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("Running thread using anonymous class");
}
};
Thread thread = new Thread(runnable);

If you look at above code the actual functionality of the thread is written in the run() method. And we are creating an anonymous class object just to define a single method which is really unnecessary if we can do functional programming (just create the function where it needs). So here the creation of anonymous class Can be replaced by lambda as below which is just a single line of code:

Runnable runnable = () -> System.out.println("Running thread using lambda expression");
Thread thread = new Thread(runnable);

Above we have assigned a lambda to the reference variable but more precisely we create a thread as below if r is not reusable.

Thread t = new Thread(() -> System.out.println("Running thread using lambda expression"));

How to write Lambda Expression

Through lambda expression, we can write functional code but this is still not similar to other functional programming languages like C, C++, JavaScript.

Java is still a class based object oriented language and methods always belong to some class, abstract class or interface. So methods implemented using lambda expression must have to define somewhere. So along with Lambda Expression Oracle engineers have applied some tweaks and introduced the concept of Functional Interfaces.

Functional Interface → An interface with only one abstract method and optionally annotated with @FunctionalInterface annotation.

We can use lambda expressions only with Functional interfaces, in above example the Runnable interface is a functional interface.
Lambda expressions in Java is usual written using syntax (argument) -> (body)

lambda expression syntax

Converting anonymous classes to Lambda Expression

After little bit practice, you will not feel any need for conversion, you will start writing lambdas without any confusion. But whenever you got confused conversion approach is the best way to create lambdas.

We can convert the old anonymous class code to lambda expression as below, suppose we want to create lambda expression for thread generation process:

Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("In thread");
System.out.println("doing something");
}
};

Remove below things in order
→ new keyword new,
→ class name and it’s parentheses Runnable(),
→ class opening and closing braces { };,
@Override annotation (if have any),
→ remove method declaration (leave argument parentheses ()) public void run
→ removing method opening { and closing braces } is not necessary, however, if you have single line of code in it then you can remove them
→ add -> between parentheses () and execution code inside { }

Runnable runnable = new Runnable() {
@Override
public void run
() -> {
System.out.println("In thread");
System.out.println("doing something");
}
};

So now our lambda expression will become

Runnable runnable = () -> {
System.out.println("In thread");
System.out.println("doing something");
}

Single line Zero Argument method: If we have a single line of code inside execution block {} then we can remove them.

Runnable r = () -> System.out.println("In thread");

Multiple Argument Methods: If functional interface’s method definition have arguments then we can write them inside ()

Comparator<Integer> comparator = (Integer i, Integer j) -> i.compareTo(j);

Single Argument Methods: And if there is only one argument then we can eliminate () braces
Consumer<String> consumer = obj -> System.out.println(obj);

Difference between Lambda Expression and Anonymous class

  • An anonymous class object creates a separate class file after compilation which increases the size jar while after compilation Lambda expression becomes invokedynamic which dynamic language implementation.
  • We can use this keyword to represent the current class in lambda expression while in the case of anonymous class this keyword represents that particular anonymous class.
  • In the case of Lambda expression, we need to provide the function body only while in the case of anonymous class we need to write the redundant class definition.

Advantages of Lambda Expression

Lambda Expressions allows us to code in functional style so it provides all benefits of functional style as well as above we can see Lambda Expressions lets developers
  • Simply understand the code.
  • Simplify and shorten their code.
  • Making it more readable and maintainable.
  • Remove more verbose class declarations.

Examples of Lambda Expressions

In below program, I have demonstrated different examples you can also found the source code on Github.

package org.programming.mitra.exercises;

import java.awt.Button;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Comparator;
import java.util.function.Consumer;
import java.util.stream.IntStream;

public class LambdaExpression {

@SuppressWarnings("unused")
public static void main(String[] args) {

// Example : Thread Creation
// Old Way
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("Running thread using anonymous class");
}
};
Thread thread = new Thread(runnable);
thread.start();

// New Way
runnable = () -> System.out.println("Running thread using lambda expression");
thread = new Thread(runnable);
thread.start();

// Example : Comparator Creation
Comparator<Integer> comparator = (Integer i, Integer j) -> i.compareTo(j);

// Example : Consumer Creation
Consumer<String> consumer = obj -> System.out.println(obj);

// Example : Consumer Creation
Button button = new Button();

// Old way:
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("button clicked");
}
});

// New way:
button.addActionListener((e) -> {
System.out.println("button clicked");
});

// Example : Iteration
System.out.println("####### Old way #######");
for (int i = 1; i < 10; i++) {
int j = i * i;
System.out.println(j);
}

System.out.println("####### Lambda (Stream) way #######");
IntStream.range(1, 10)
.map(num -> num * num)
.forEach(i -> System.out.println(i));

}
}

Lambda expressions are heavily used in Java Stream API, which I am going to cover in later articles.

Comments

  1. I think that thanks for the information and insights you have so provided here.
    java tips

    ReplyDelete
  2. Very informative article.Thank you author for posting this kind of article .



    http://www.wikitechy.com/view-article/oops-concept-in-java-with-example



    Both are really good,
    Cheers,
    Venkat

    ReplyDelete
  3. You explained very well in simple way and there all the examples of java 8 new features Lambda Expressions is quite useful.
    thanks for this nice post.

    ReplyDelete

Post a Comment

Popular posts from this blog

Why an outer Java class can’t be static

In a previous blog , I talked about why we can not define an outer class using private or protected keywords. If you have not read it, please go ahead and give it a look. I this article I will talk what is the use of the static keyword, why an outer Java class can’t be static, why it is not allowed in Java to define a static outer class. In order to understand that first, we need to understand what is the static keyword used for, what purpose it solves and how does it works. What does static keyword do Every Java programmer knows that if we need to define some behavior (method) or state (field) which will be common to all objects we define it as static. Because static content (behavior or state) does not belong to any particular instance or object, it will common to all objects and all objects are free to change any static field and every change will be visible to every object. We do not need to create any object of the class to access a static field or method, we can directly...

Why Single Java Source File Can Not Have More Than One public class

According to Java standards and common practices we should declare every class in its own source file. And even if we declare multiple classes in the single source file (.java) still each class will have its own class file after compilation. But the fact is that we can declare more than one class in a single source file with below constraints, Each source file should contain only one public class and the name of that public class should be similar to the name of the source file. If you are declaring the main method in your source file then main should lie in that public class If there is no public class in the source file then main method can lie in any class and we can give any name to the source file. If you are not following 1st constraint then you will receive a compilation error saying “ The public type A must be defined in its own file ”.  While if you are not following the second constraint you will receive an error “ Error: Could not find or load main class User ” after ...

How Does JVM Handle Method Overloading and Overriding Internally

In my previous article Everything About Method Overloading Vs Method Overriding , I have discussed method overloading and overriding, their rules and differences. In this article, we will see How Does JVM Handle Method Overloading And Overriding Internally, how JVM identifies which method should get called. Let’s take the example of parent class  Mammal and a child  Human classes from our previous blog to understand it more clearly. public class OverridingInternalExample { private static class Mammal { public void speak() { System.out.println("ohlllalalalalalaoaoaoa"); } } private static class Human extends Mammal { @Override public void speak() { System.out.println("Hello"); } // Valid overload of speak public void speak(String language) { if (language.equals("Hindi")) System.out.println("Namaste"); else System.out.println("Hello"); } @...