Lambda Expression in Java

Challenge Inside! : Find out where you stand! Try quiz, solve problems & win rewards!

Learn via video course

Java Course - Mastering the Fundamentals
Java Course - Mastering the Fundamentals
By Tarun Luthra
Free
star5
Enrolled: 1000
Java Course - Mastering the Fundamentals
Java Course - Mastering the Fundamentals
Tarun Luthra
Free
5
icon_usercirclecheck-01Enrolled: 1000
Start Learning

Overview

Lambda expression in java is an anonymous (no name) function that does not need to define the data type of input parameters and does not need to have a return type. Lambda expression in java implements the functional interface and it can be treated as any other java object. It can be used to create threads, comparators and can be used to add event Listeners.

Scope of article

  • This article covers the syntax of Lambda expression in java with several examples.
  • It will also take you through the advantages and disadvantages of Lambda and access variables.

What is lambda expression in java

Remember the difficulty of utilising anonymous inner classes to implement one-function interfaces (functional interface in java8)? Don't worry, we've provided an example to refresh your memory. Take a look at the one-function interface described below.

Before Java8, the best way to implement this example interface was to use anonymous inner classes, as shown in the code below.

In java8 you can use a lambda expression to implement this interface. Like this:

This is the Lambda expression in the code above.

You can see how simple it is to implement the functional interface using a lambda expression. Lambda expression in java is a feature introduced in Java 8 that adds functional programming techniques to Java, making it easier to write Java code in specific situations as with Java anonymous inner classes. Lambda expressions combine functional programming features with Java's object-oriented programming characteristics, resulting in more powerful concurrency features that are easier to use. A lambda expression is an anonymous function, which means it doesn't have a name and isn't bound by any return type constraints.

A class that has no name is known as an anonymous inner class in Java. It should be used if you have to override a method of class or interface.

You must either design your functional interface or use the default functional interface given by Java to use a lambda expression. Functional interfaces (or Single Abstract Method Interfaces) are interfaces that have only one abstract method, such as Runnable, Callable, and ActionListener.

Java Lambda Expression Syntax

The Syntax of Lambda Expression in Java consists of three components.

  1. Arguments-list: It is the first portion of the Lambda expression in Java. It can also be empty or non-empty. In the expression, it is enclosed by a round bracket.
  2. Lambda operator ->: It's an arrow sign that appears after the list of arguments. It connects the arguments-list with the body of the expression.
  3. Body: It contains the function body of lambda expression. It is surrounded by curly brackets.

The following is the general syntax of a lambda expression in Java.

We'll go over the syntax for three different instances to obtain a better understanding of Lambda expressions in Java.

1. No Parameter Syntax

It is the case when the function does not require any input parameter, so don't provide anything in the parameters and the rest of the things are the same.

2. One Parameter Syntax

We only need to pass one input parameter in this situation; however, while using lambda, we don't need to specify the data type of input parameters because the compiler discovers it automatically.

3. Two Parameter Syntax

The case, as the name implies, refers to a circumstance in which two input parameters are necessary.

Lambda Use Cases in Java

Lambda expressions are used to replicate the functionality of an anonymous class without the need for a complex implementation. They're ideal for repeating simple behaviours that may be utilised throughout the program, like adding two values without modifying the input data.

Lambda is extremely beneficial for functional programming approaches in Java because of these qualities.

Functional programming is a programming paradigm that seeks to apply and combine functions to create programmes.

The following are the five fundamental principles of functional programming:

1. First-class functions

When functions in a programming language are handled like any other variable, the language is said to have first-class functions. In such a language, for example, a function can be supplied as an argument to other functions, returned by another function, and assigned as a value to a variable.

2. Function Composition

Function composition is the act of combining simple functions to create more complex ones. In Java, you can use the compose and andThen methods of the Function interface to perform function composition.

3. Pure functions

Pure function is functions that operate independently of the state outside the function and contain only the operations required to find the output. In Java, you can create pure functions by avoiding mutable state, global variables, and side effects such as I/O operations. Pure functions can help you write more predictable and reliable code.

4. Immutability

An immutable object is one whose state cannot be changed after it is created. In the immutable functions, inputs are only referred to; they are not changed. Complex conditional behaviour should be avoided in functions. In general, no matter how many times a function is called, it should always return the same value.

5. Higher-order functions

A higher-order function is a function that accepts other functions as parameters and/or uses a function as the return value. These are essential to creating complex behaviours with functional programming.

In Java, lambda expressions allow us to accomplish the ideas of pure functions, immutability, and first-class functions. Lambda functions are pure in the sense that they do not rely on a specific class scope. They are immutable because they refer to the provided argument but do not change its value to achieve their effect. Finally, they are first-class functions since they can be handed to other functions while remaining anonymous. Because of their class independence, lambda expressions are also utilised as event receivers and callback functions in non-functional programming.

Java Lambda expression Examples

We already know that to use Lambda expressions in Java, we require a functional interface. We can utilise built-in java functional interfaces like Runnable, or we can write our interfaces in java, the syntax for which is shown below.

Example 1 - Without Using Lambda expression

We can implement the functional interface in Java without utilising Lambda expressions by using an anonymous class.

The code below implements a functional interface named MyName and overrides its only abstract method with the help of an anonymous class.

Output:

  • The goal of this example is to use an anonymous class to implement a functional interface.
  • On top, we defined a functional interface called MyName, which includes a void method called SayMyName.
  • Then, in the main method, we override the SayMyName function for an object person of the MyName interface with an anonymous class.
  • And then we called the SayMyName function for the same object, which Will print the name Himanshu.

Example 2 - By using Lambda expression

In this example, we will utilise a lambda expression in Java to implement the same MyName interface as in the previous example.

Output:

  • In the same way as we did in the previous example, we constructed a functional interface called MyName, which has one void method called SayMyName.
  • We utilised lambda expressions in the main function to override the interface's only function.
  • We did use the lambda syntax that we covered earlier.
  • Because the function does not accept any parameters, the () is empty.
  • Inside the body, we provide a print statement that will allow us to print the name Himanshu Yadav.
  • After the curly bracket, a semi-colon (;) was added.
  • Then we called the SayMyName function for the created object p2.

Example 3: Java Lambda Expression with no parameter

In this example, we'll use java lambda expressions to create a single interface that doesn't take any input parameters.

In the code below we created a functional interface named speaker, the speaker has a function named say, which returns a string. We use the Lambda expression in Java to override the say function in the main function, just as we did in the previous example. Finally, we added a print statement to output the value returned by the say function.

Output:

Example 4: Java Lambda Expression with a single parameter

In this example, we'll look at a lambda function that only accepts one parameter. We'll design a functional interface and a function that accepts a single parameter and similar to the previous examples we'll override it with a lambda expression in Java.

Output:

  • We established a functional interface in the code above that has a function named say() that takes a string as input and returns a string.
  • We use three separate Lambda expressions in Java to override the say() method in the main function.
  • We are familiar with the first Lambda expression, it follows the same syntax we discussed earlier.
  • It takes the string name as input and returns the string "hello, "+name.
  • Since we have only one input parameter, it's optional to use a round bracket around parameters, so we omit them in the second implementation of Lambda expression in java.
  • The usage of a curly bracket and a return statement is optional because the function body just includes one statement. In the third Lambda expression, we leave them out.
  • Respective print statements are added for each result.

Example 5: Java Lambda Expression with Multiple Parameters

We will consider many input parameter possibilities for our lambda expression in this example. We will create a program to add two numbers using the Lamda expression in java.

Output:

  • We constructed the MyInter functional interface, which has the add() function. Add accepts two integer parameters and returns an integer.
  • To override the function in the main function, we utilise Lambda expressions with and without the parameters data type.
  • Finally respective print statements are added for each result.

Example 6: Iterating Collections Using the Foreach Loop

In this example, we'll use a forEach loop in Java to run over a list of names, then use a lambda expression in Java to grab the element from the list and print it.

Output:

In the code above we firstly created a list of names. We used a foreach loop to iterate through the list and Lambda expression to simultaneously grab the element and print it.

Example 7: Java Lambda Expression With or Without Return Keyword

As discussed in example 4, if there is only one statement in a Java lambda expression, you can avoid using the return keyword. When a lambda expression comprises multiple statements, you must use the return keyword.

Output:

Example 8: Java Lambda Expression - Creating Thread

To run the thread, you can use a lambda expression. In the following example, we use a lambda expression in Java to implement the run method.

In Java, a thread is just a single independent execution path for a set of statements. It is the process of carrying out a task from start to end.

In the code below we will see two different implementations to create tread on Runnable interface. One is without Lambda and another one is with Lamda expression.

Output

  • In the code above we firstly create a thread, thread1 using anonymous class implementation, to do so,
  • We create a Runnable interface object t1 and override the run function using an anonymous class.
  • Then we create a thread class object thread1 by providing t1 as input.
  • And finally we start the thread1 using the start() method, which will run the overridden function in the interface and the result is printed.
  • In the second half of the code, we use lambda expression implementation to create thread2 and the rest of the things are the same.

Example 9: Java Lambda Expression - Comparator

When we wish to sort a collection of items that can be compared, we utilise a comparator. This comparison can also be done with the Comparable interface, but it only allows you to compare these objects in a single particular criteria only. You must only use Comparator if you wish to sort this collection based on several criteria/fields.

  • In the code below we create a person class that keeps track of the age and name of the person.
  • Then we put three-person objects into a list and sort them by person name.
  • To sort the list we use the comparator with a lambda expression as shown in the code.
  • Finally we have a name wise sorted list.

Output:

Example 10: Java Lambda Expression - Filter Collection Data

Java is equipped with filter() method inside the stream class and we can use Lambda expression in java to provide the condition to the filter. See the example below.

In this example, we will use the same person class used in the previous example and will try to filter data using Lambda expression in java.

Output

  • In the above code, we utilized the same person class as the previous example and put some data into it.
  • Then we created a stream class object filtered_data, which as the name suggest stores the data filtered by the filter() function which uses a lambda expression to keep the data with age more than 20 only.
  • As used earlier finally iterate through the filtered_data sequence and print the result with the help of Lambda expression and foreach loop in java.

Example 11: Java Lambda Expression - Event Listener

In this example, we will see how we can use Lambda Expression in java to addEventListner and we will also compare it with the traditional (before java8) method of adding eventListners.

In Java, an event listener is an object that "listens" for an event, such as a mouse click or a keypress, and then responds appropriately. The event object that defines the event must be attached to an event listener.

Before Java 8, it was fairly usual to utilise an anonymous class to handle a JButton's click event. Here is the syntax for the same.

  • The addActionListener() method is used with an anonymous class that implements the ActionListener interface. The event handler code is then inserted inside the actionPerformed() method, as is usual.
  • Because the ActionListener interface just has one method, actionPerformed(), it's a functional interface, therefore Lambda expressions can be used to replace reusable code. The following is a rewrite of the previous example using Lambda expressions:

Lambdas as Objects

A lambda expression in Java is an object. A lambda expression can be assigned to a variable and passed around like any other object. Here's an illustration:

Output:

  • In the code above us, first of all, create a functional interface MyComparator, which has one function which takes two integers as input and returns true if the first integer is greater than false otherwise.
  • In the main function, we assign the return value of Lambda expression to boolean variable result, which shows that Lambda can be treated as a java object.

Accessible Variable

Under some conditions, a Java lambda expression can access variables defined outside the lambda function body.

Java lambdas can access the following types of variables:

  • Local Variable
  • Instance variables
  • Static variables

In the subsequent sections, we go over each one in-depth.

1. Local Variables

Lambda Expressions in java have the access to local variables of the enclosing scope. We need to follow some rules in the case of local variables in lambda expressions.

  • We can't declare a local variable with the same name that is already declared in the enclosing scope of a lambda expression since a lambda expression can't define any new scope as an anonymous inner class does.
  • We can't assign any value to a local variable declared outside the lambda expression inside the lambda expression. Because local variables declared outside of a lambda expression may be final or effectively final.
  • The this and super references inside a lambda expression body are the same as their enclosing scope. Because lambda expressions can't define any new scope.

Output:

As you can see, the lambda body now refers to the outside-the-lambda-body declared local variable s1. This is only permitted if the variable being referred to is "effectively final," that is, its value does not change after it is allocated. The compiler would complain about the reference to the s1 variable from inside the lambda body if its value was modified later.

2. Instance variables

Instance variables in Java are non-static variables that are defined in a class outside any method, constructor or block. Each instantiated object of the class has a separate copy or instance of that variable. An instance variable belongs to a class.

An instance variable can also be accessed via a Lambda expression. The value of the instance variable can be updated by the Java developer even after it has been defined, and the value will be altered inside the lambda as well.

output:

Notice the reference to variable a inside the lambda body. This captures the instance variable a of the enclosing MyClass object. It is even possible to change the value of the instance variable after its capture - and the value will be reflected inside the lambda.

3. Static variables

In Java, a static variable is a variable that belongs to a class and is only initialised once during execution. It's a class-specific variable, not an object-specific variable (instance ). Only once, at the start of the execution, are static variables initialised.

Static variables can also be accessed via a Java lambda expression. This is unsurprising, given that static variables can be accessed from anywhere in a Java application as long as the static variable is accessible (packaged scoped or public).

Output:

Lambda Expressions vs. Anonymous Interface Implementations

Despite the fact that lambda expressions are similar to anonymous interface implementations, there are a few peculiarities to be aware of.

The main difference is that a lambda expression cannot have a state (member variables), whereas an anonymous interface implementation can. Consider the following user interface:

An anonymous interface implementation, like this one, can be used to implement this interface:

This anonymous Consumer solution can maintain its internal state. Consider the following example:

  • It's worth noting that the anonymous Consumer implementation now has the eventCount field.
  • A lambda expression cannot have such fields. A lambda expression is thus said to be stateless.

Advantages of Lambda Expression

One of the most significant advantages of a lambda expression is that it reduces the amount of code. Lambda expressions can only be used with a functional interface, as we know. Because Runnable has a functional interface, we can use lambda expressions with convenience.

Lambda Makes it easy to work with stream APIs and we get more Efficiency when doing bulk operations on collections, we can obtain higher efficiency (parallel processing) by leveraging the Stream API and lambda expressions. Additionally, lambda expressions aid in collection internal iteration rather than external iteration.

Disadvantages of Lambda Expression in Java

  • Lambda expressions (as well as anonymous classes) in Java can only access the final (or effectively final) variables of the enclosing scope.
  • Lambda functions themselves lack names and documentation, meaning that the only way to know what they do is to read the code.

Important points to Remember

  • A lambda expression is an implementation of a functional interface.
  • A Lambda Expression is an anonymous function that does not need to have a return type and input parameter data type.
  • Be aware of the scope of variable you are using in the lambda expression.

Conclusion

  • We have learned how to implement functional interfaces using Lambda expression in java and using anonymous class as well.
  • We have gone through several examples, variable accessibility, advantages and disadvantages of lambda expression in java.
  • Lamda expression is easy to use and makes the code look much better.