Lambda Expression in Java
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.
What is lambda expression in java
Lambda expression in Java is a feature introduced in Java 8 that allows you to implement one-function interfaces (functional interfaces) more simply and concisely. It is an anonymous function that adds functional programming techniques to Java, making it easier to write code in specific situations compared to using anonymous inner classes.
A lambda expression is represented as:
Lambda expressions are used with functional interfaces, which are interfaces that have only one abstract method, such as Runnable, Callable, and ActionListener.
Java Lambda Expression Syntax
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. Multiple 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 in Java are used to simplify the functionality of anonymous classes, making it easy to repeat simple behaviors without complex implementations.
The five fundamental principles of functional programming in Java are:
- First-class functions: Functions can be treated like variables, passed as arguments, returned by other functions, and assigned to variables.
- Function Composition: Combining simple functions to create more complex ones using compose and andThen methods of the Function interface.
- Pure functions: Functions that operate independently of external state and avoid side effects, leading to more predictable and reliable code.
- Immutability: Functions should not change input data; immutable objects maintain their state after creation.
- Higher-order functions: Functions that accept other functions as parameters or return functions as their result.
Java Lambda expression Examples
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.
Example 2 - By using Lambda expression
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.
Example 4: Java Lambda Expression with a single parameter
In this example, we'll look at a lambda function that only accepts one parameter.
Example 5: Java Lambda Expression with Multiple Parameters
We will consider many input parameter possibilities for our lambda expression in this example.
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.
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.
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 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.
- 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.
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.
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.
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:
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.
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.
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. Use this Compiler to compile your Java code.
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).
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.
- 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.