Java Lambda Expression
What is a Lambda?
A lambda expression is an anonymous function
A function without name
Without access modifier
Without return type
Lambda provides a clear and concise way to implement functional interface(interface with exactly one abstract method.)
Note: Lambda expression is specific to Functional interface only without it we can't write lambda expressions.
A lambda expression is NOT an object - it is an instance of a functional interface. The JVM uses invoke dynamic to implement lambdas efficiently(no new class file per lambda).
Lambda Syntax & Examples
| Form | Syntax |
|---|---|
| No params | () -> expression |
| Single param | x -> expression |
| Single param types | (Type x) -> expression |
| Multiple Params | (x,y) -> expression |
| Block params | (x)-> {statement;return x;} |
| void block | (x)-> {statement;} |
Learn to write your first lambda expression
Generally, we write method in java like below
public void methodName(){
System.out.println("first lambda expression");
}
for lambda expression, we don't need method name, access modifier and return type, so it will look like below
() -> {
System.out.println("first lambda expression");
}
for single statement, no curly braces required.
() -> System.out.println("first lambda expression");
complete code of no param
@java.lang.FunctionalInterface
interface FunctionalInterface{
void methodName();
}
public class LambdaExpression {
public static void main(String[] args) {
FunctionalInterface i = ()-> System.out.println("first lambda expression");
i.methodName();
}
}
single param
@java.lang.FunctionalInterface
interface FunctionalInterface{
int square(int num);
}
public class LambdaExpression {
public static void main(String[] args) {
FunctionalInterface i = x -> x * x;
System.out.println(i.square(10));
}
}
single param typed
@java.lang.FunctionalInterface
interface FunctionalInterface{
int lengthOfString(String s);
}
public class LambdaExpression {
public static void main(String[] args) {
FunctionalInterface i = (String s) -> s.length();
System.out.println(i.lengthOfString("amol"));
}
}
multiple params
@java.lang.FunctionalInterface
interface FunctionalInterface{
int sum(int num1, int num2);
}
public class LambdaExpression {
public static void main(String[] args) {
FunctionalInterface i = (x,y) -> x + y;
System.out.println(i.sum(10,20));
}
}
block body
@java.lang.FunctionalInterface
interface FunctionalInterface{
int sum(int num1, int num2);
}
public class LambdaExpression {
public static void main(String[] args) {
FunctionalInterface i = (x,y) -> {
System.out.println("side effect");
return x + y;
};
System.out.println(i.sum(10,20));
}
}
void block
@java.lang.FunctionalInterface
interface FunctionalInterface{
void printMessage();
}
public class LambdaExpression {
public static void main(String[] args) {
FunctionalInterface i = () -> {
System.out.println("side effect");
};
i.printMessage();
}
}
Identify valid/invalid lambda expression
n -> return n*n;//invalid- missing curly braces
n-> {return n*n;};//valid
n-> {return n*n};//invalid, missing semi-colon after return expression
n->{n*n;};//invalid, missing return keyword
n-> n*n;//valid- valid way of using
Lambda expression with Multi-threading
public class LambdaWithMultithreading {
public static void main(String[] args) {
Runnable r = () -> {
for (int i=0;i<5;i++){
System.out.println("child thread..");
}
};
Thread t = new Thread(r);
t.start();
}
}
output
child thread..
child thread..
child thread..
child thread..
child thread..
Comparator demo without lambda
import java.util.*;
import java.util.Comparator;
public class ComparatorWithoutLambda implements Comparator<Integer> {
@Override
public int compare(Integer n1, Integer n2) {
return n1 > n2 ? -1: n1 < n2? 1:0;
}
public static void main(String[] args) {
List<Integer> l = Arrays.asList(2,1,3,4);
// Collections.sort(l); // follows default sorting order
// System.out.println(l);
Collections.sort(l,new ComparatorWithoutLambda());
System.out.println(l);
}
}
output
[4, 3, 2, 1]
Comparator with lambda expression
public class ComparatorWithLambda {
public static void main(String[] args) {
List<Integer> l = Arrays.asList(2,1,3,4,6,5);
Comparator<Integer> c = (n1,n2) -> n1 > n2?-1:n1 < n2 ? 1:0;
Collections.sort(l,c);
System.out.println(l);
}
}
output
[6, 5, 4, 3, 2, 1]
Comparator demo with lambda expression for custom object
import java.util.*;
class Student{
int sid;
String stdName;
public Student(int id, String name){
this.sid = id;
this.stdName = name;
}
public String toString(){
return this.sid+" - "+this.stdName;
}
}
public class LambdaWithCustomObject {
public static void main(String[] args) {
List<Student> stdList = Arrays.asList(new Student(103,"amol"),new Student(101,"sagar"),
new Student(102, "prashant"),new Student(104,"arjun"));
System.out.println(stdList);
/*
reverse sorting based on student id
*/
Comparator<Student> s = (s1,s2)-> Integer.compare(s1.sid, s2.sid);
Collections.sort(stdList,s);
System.out.println("sorting based on id: "+stdList);
/*
reverse sorting based on student name
*/
Comparator<Student> sname = (s1,s2) -> s2.stdName.compareTo(s1.stdName);
Collections.sort(stdList,sname);
System.out.println("sorting based on name"+ stdList);
}
}
output
[103 - amol, 101 - sagar, 102 - prashant, 104 - arjun]
sorting based on id: [101 - sagar, 102 - prashant, 103 - amol, 104 - arjun]
sorting based on name[101 - sagar, 102 - prashant, 104 - arjun, 103 - amol]
Anonymous Inner class vs Lambda Expression
We are writing a class which is extending to the thread class.
Note - This doesn't have any name, called anonymous class
Thread t=new Thread{
public void run(){
}
// t is the object of child class of Thread
};
Now, we will create a anonymous class which will implement the Runnable interface.
Runnable r=new Runnable(){
public void run(){
}
//r is the object of class which is implementating Runnable interface.
};
Anonymous inner class is not equivalent to the lambda expression.
If anonymous inner class implements a interface which contains single abstract method then only we can replace that anonymous inner class with lambda expression.
Anonymous inner class can extend normal class.
Anonymous inner class can extend abstract class
Anonymous Inner class can implement interface, which might contain any number of abstract methods.
Lambda expression can implement interface which contains a single abstract method.
Variable Capture(closure)
Lambdas can capture variables from their enclosing scope, but ONLY if those variables are effective final(value never changed after initialization)
public class EffectiveFinalDemo {
public static void main(String[] args) {
int base = 30;
Function<Integer, Integer> f = x -> x + base; //valid
System.out.println(f.apply(20));
// base = 100; // Invalid - compile error - Variable used in lambda expression should be final or effectively final
}
}
output
50

