Oops.complete.JavaCheatSheet
Oops.complete.JavaCheatSheet
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.
// Before Java 8
MyInter person = new MyInter() {
@Override
public void MyInterMethod() {
System.out.println("Before Java 8 without lambda");
}
};
Lambda expressions are used with functional interfaces, which are interfaces that have only one abstract
method, such as Runnable, Callable, and ActionListener.
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.
// No 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.
The case, as the name implies, refers to a circumstance in which two input parameters are necessary.
1. First-class functions: Functions can be treated like variables, passed as arguments, returned by other
functions, and assigned to variables.
2. Function Composition: Combining simple functions to create more complex ones
using compose and andThen methods of the Function interface.
3. Pure functions: Functions that operate independently of external state and avoid side effects, leading to
more predictable and reliable code.
4. Immutability: Functions should not change input data; immutable objects maintain their state after
creation.
5. Higher-order functions: Functions that accept other functions as parameters or return functions as their
result.
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.
@FunctionalInterface
interface MyName{
public void SayMyName();
}
public class LambdaExpressionExample {
public static void main(String[] args) {
Output:
Himanshu
MyName p2 = () -> {
System.out.println("Himanshu Yadav");
};
// function call.
p2.SayMyName();
}
}
Output:
Himanshu Yadav
In this example, we'll use java lambda expressions to create a single interface that doesn't take any input
parameters.
interface speaker {
public String say();
}
public class LambdaExpressionExample {
public static void main(String[] args) {
speaker s = () -> {
return "Scaler has best content.";
};
System.out.println(s.say());
}
}
Output:
In this example, we'll look at a lambda function that only accepts one parameter.
interface Speaker{
public String say(String name);
}
System.out.println(s1.say("Himanshu"));
System.out.println(s2.say("Scaler"));
System.out.println(s3.say("Content"));
}
}
Output:
Hello, Himanshu
Hello, Scaler
Hello, Content
We will consider many input parameter possibilities for our lambda expression in this example.
interface MyInter{
int add(int a,int b);
}
System.out.println(ad1.add(100,200));
// Multiple parameters with data type in the lambda expression
System.out.println(ad2.add(200,300));
}
}
Output:
300
500
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.
import java.util.*;
public class LambdaExpressionExample{
public static void main(String[] args) {
list.add("Himanshu");
list.add("Jatin");
list.add("Virat");
list.add("Jai");
list.forEach(
(element)->System.out.println(element)
);
}
}
Output:
Himanshu
Jatin
Virat
Jai
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.
interface MyInter{
int add(int a,int b);
}
System.out.println(ad2.add(100,200));
}
}
Output:
120
300
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.
Runnable t2 = () -> {
System.out.println("This is thread2...");
};
Output
This is thread1...
This is thread2...
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.
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.
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
class Person{
int age;
String name;
Collections.sort(list,(p1,p2)->{
return p1.name.compareTo(p2.name);
});
for(Person p:list){
System.out.println( p.name+" "+p.age);
}
}
}
Output:
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.
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
class Person{
int age;
String name;
}
}
public class LambdaExpressionExample11{
public static void main(String[] args) {
}
}
Output
Himanshu: 21
Jatin: 27
Shabina: 34
Shyam: 26
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.
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
System.out.println("Handled by anonymous class listener");
}
});
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:
interface MyComparator {
}
public class LambdaExpressionExample {
public static void main(String[] args) {
Output:
false
Accessible Variable
Under some conditions, a Java lambda expression can access variables defined outside the lambda function
body.
Local Variable
Instance variables
Static variables
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.
interface MyInter {
}
public class LambdaExpressionExample6 {
public static void main(String[] args) {
String s1 = "Hello";
MyInter g1 = (str) ->{
return s1+", "+str;
};
System.out.println(g1.greet("Himanshu"));
}
}
Output:
Hello, Himanshu
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.
interface MyInter {
void print();
}
public class MyClass {
int a; // instance variable
};
output:
a = 19
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).
interface MyInter {
void print();
}
class Myclass {
t.print();
}
}
public class LambdaExpressionExample10{
public static void main(String arg[]) {
Myclass test = new Myclass();
test.show();
}
}
Output:
b = 500
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:
Consumer consumer = new Consumer() {
public void consume(Object event){
System.out.println(event.toString() + " consumed");
}
};
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.
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.
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.