Lambda Expressions in Java

Lambda expressions are known to many of us who have worked on advanced languages like Scala. The term “lambda” has its origin in Lambda calculus that uses the Greek letter lambda (λ) to denote a function abstraction.

Lambda expressions were introduced to Java as part of Java 8 release.

1. What are Lambda Expressions?

In general programming language, a Lambda expression (or function) is an anonymous function, i.e., a function without any name or identifier, and with a list of formal parameters and a body. An arrow (->) is used to separate the list of parameters and the body.

 In Java, a lambda expression is an expression that represents an instance of a functional interface.

Similar to other types in Java, lambda expressions are also typed, and their type is a functional interface type. To infer the type, the compiler looks at the left side of the assignment in a lambda expression.

Note that the lambda expression itself does not contain the information about which functional interface it is implementing. This information is deduced from the context in which expression is used.

2. Lambda Expression Example

A typical lambda expression syntax will be like this:

(parameters) -> expression

For example, the below-given lambda expression takes two parameters and returns their addition. Based on the type of x and y, the expression will be used differently.

  • If the parameters match to Integer the expression will add the two numbers.
  • If the parameters of type String the expression will concat the two strings.
(x, y) -> x + y

For example, we have the following functional interface Operator. It has one method process() that takes two parameters and returns a value.

@FunctionalInterface
interface Operator<T> {
  T process(T a, T b);
}

We can create lambda expressions for this functional interface in the following manner. Notice we are able to create the method implementations and immediately use them. We do not need to create a concrete class OperatorImpl that implements Operator interface.

Operator<Integer> addOperation = (a, b) ->  a + b;
System.out.println(addOperation.process(3, 3));     //Prints 6

Operator<String> appendOperation = (a, b) ->  a + b;
System.out.println(appendOperation.process("3", "3"));  //Prints 33

Operator<Integer> multiplyOperation = (a, b) ->  a * b;
System.out.println(multiplyOperation.process(3, 3));    //Prints 9

Two good examples of functional interface types are Consumer and BiConsumer interfaces that are heavily used in Stream API for creating lambda expressions.

3. Features of Lambda Expressions

  • A lambda expression can have zero, one or more parameters.
(x, y) -> x + y
(x, y, z) -> x + y + z
  • The body of the lambda expressions can contain zero, one or more statements. If the body of lambda expression has a single statement curly brackets are not mandatory and the return type of the anonymous function is the same as that of the body expression. When there is more than one statement in the body then these must be enclosed in curly brackets.
(parameters) -> { statements; }
  • The type of the parameters can be explicitly declared or it can be inferred from the context. In previous example, the type of addOperation and appendOperation is derived from context.
  • Multiple parameters are enclosed in mandatory parentheses and separated by commas. Empty parentheses are used to represent an empty set of parameters.
() -> expression
  • When there is a single parameter, if its type is inferred, it is not mandatory to use parentheses.
a -> return a * a;
  • A lambda expression cannot have a throws clause. It is inferred from the context of its use and its body.
  • Lambda expressions cannot be generic i.e. they cannot declare type parameters.

4. More Examples

We are listing out some code samples which you can read and analyze how a lambda expression can be used in the day-to-day programming.

Example 1: Using lambda expression to iterate over a List and perform some action on list items

In the given example, we are iterating over the list and printing all the list elements in the standard output. We can perform any desired operation in place of printing them.

List<String> pointList = new ArrayList();
 
pointList.add("1");
pointList.add("2");
 
pointList.forEach( p ->  { System.out.println(p); } );

Example 2: Using lambda expression to create and start a Thread in Java

In given example, we are passing the instance of Runnable interface into the Thread constructor.

new Thread(
    () -> System.out.println("My Runnable");
).start();

Example 3: Using lambda expression for adding an event listener to a GUI component

JButton button =  new JButton("Submit");
button.addActionListener((e) -> {
    System.out.println("Click event triggered !!");
});

Above are very basic examples of lambda expressions in java 8. I will be coming up with more useful examples and code samples from time to time.

5. Advantages of Lambda Expressions

Lambda expressions enable many benefits of functional programming to Java. Like most OOP languages, Java is built around classes and objects and treats only the classes as their first-class citizens. The other important programming entities, such as functions, take the back seat.

But in functional programming, we can define functions, give them reference variables, and pass them as method arguments and much more. JavaScript is a good example of functional programming where we can pass callback methods to Ajax calls and so on.

Note that we were able to do everything prior to Java 8 using anonymous classes that we can do with lambda expressions, but they use a very concise syntax to achieve the same result. Let us see the comparison of the same method implementation using both techniques.

//Using lambda expression
Operator<Integer> addOperation = (a, b) -> a + b;

//Using anonymous class
Operator<Integer> addOperation = new Operator<Integer>() {
  @Override
  public Integer process(Integer a, Integer b) {
    return a + b;
  }
};

Lambda expression is a very useful feature and has been lacking in Java from the beginning. Now with Java 8, we can also use functional programming concepts with the help of this.

Happy Learning !!

Leave a Reply

18 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions, and frequently asked interview questions.

Our Blogs

REST API Tutorial