1. What is a Lambda Expression?
Lambda Expressions are a Java 8 language feature that allows us to consider actions as objects.
In Java, lambda expressions basically express instances of functional interfaces. An interface with a single abstract method is called a functional interface.
Lambda expressions are short blocks of code that accept input as parameters and return a resultant value.
Definition
A Lambda Expression is an anonymous (nameless) function. It does not have a name, return type, or access modifier.
Lambda expressions are also known as anonymous functions or closures.
2. Why Use Lambda Expressions?
- To provide the implementation of a Functional Interface.
- Less coding.
- Enable functionality to be treated as a method argument, or code as data.
- A function can be created without belonging directly to a named class.
- A lambda expression can be passed around like an object and executed on demand.
3. Parts of a Lambda Expression
->| Part | Description |
|---|---|
| Argument List | Can be empty or non-empty. |
| Arrow Token | Links the argument list and the body of the expression. |
| Body | Contains expressions and statements for the lambda expression. |
(Argument List) -> { expression; }
4. How to Write a Lambda Expression
Consider a traditional method for adding two numbers and printing the result:
private void add(int i, int j) {
System.out.println(i + j);
}
void add(int i, int j) {
System.out.println(i + j);
}
add(int i, int j) {
System.out.println(i + j);
}
(int i, int j) {
System.out.println(i + j);
}
(int i, int j) -> {
System.out.println(i + j);
}
(i, j) -> {
System.out.println(i + j);
}
(i, j) -> {
System.out.println(i + j);
}
5. Lambda Expression Examples
Example 1 — Print "Hello Java 8"
public void m1() {
System.out.println("Hello Java 8");
}
// Lambda form
() -> {
System.out.println("Hello Java 8");
}
Example 2 — Multiply Two Numbers
public void add(int a, int b) {
System.out.println(a * b);
}
// Remove method declaration elements
(int a, int b) -> System.out.println(a * b);
// Type inference
(a, b) -> System.out.println(a * b);
Example 3 — String Operation
public String m2(String str1) {
return str2;
}
// Lambda form
(String str1) -> return str2;
// Simplified
(str1) -> str2;
6. Lambda Expression Syntax
lambda operator -> body
(Argument List) -> {expression;}
Example with Two Arguments
(int arg1, String arg2) -> {
System.out.println(
"Two arguments " + arg1 + " and " + arg2
);
}
| Component | Example |
|---|---|
| Argument List | (int arg1, String arg2) |
| Arrow Token | -> |
| Body | { System.out.println(...); } |
7. Lambda Expression Parameters
The notes describe three forms:
1. Zero Parameter
No arguments.
2. Single Parameter
One argument.
3. Multiple Parameters
Two or more arguments.
Zero Parameter
() -> System.out.println("Zero parameter lambda");
Single Parameter
(p) -> System.out.println("One parameter: " + p);
It is not mandatory to use parentheses when the parameter type can be inferred from the context.
Multiple Parameters
(p1, p2) -> System.out.println(
"Multiple parameters: " + p1 + ", " + p2
);
- The body can contain zero, one, or more statements.
- For a single statement, curly braces are not mandatory and the return type of the anonymous function is the same as the body expression.
- For multiple statements, curly braces are required and the return type is the same as the value returned within the code block, or
voidif nothing is returned.
8. Lambda with ArrayList and forEach()
// {1, 2, 3, 4}
ArrayList<Integer> arrL = new ArrayList<Integer>();
arrL.add(1);
arrL.add(2);
arrL.add(3);
arrL.add(4);
// Using lambda expression to print all elements
arrL.forEach(n -> System.out.println(n));
// Using lambda expression to print even elements
arrL.forEach(n -> {
if (n % 2 == 0)
System.out.println(n);
});
9. Functional Interface Example
// Java program to demonstrate lambda expressions
// to implement a user defined functional interface.
// A sample functional interface
// An interface with single abstract method
interface FuncInterface {
// An abstract function
void abstractFun(int x);
// A non-abstract (default) function
default void normalFun() {
System.out.println("Hello");
}
}
Using the Functional Interface
class Test {
public static void main(String args[]) {
// Lambda expression to implement
// above functional interface
FuncInterface fobj =
(int x) -> System.out.println(2 * x);
// Calls lambda expression and prints 10
fobj.abstractFun(5);
}
}
10. Lambda with Multiple Functional Behaviors
public class Test {
interface FuncInter1 {
int operation(int a, int b);
}
interface FuncInter2 {
void sayMessage(String message);
}
// Performs FuncInter1's operation
private int operate(int a, int b, FuncInter1 fobj) {
return fobj.operation(a, b);
}
public static void main(String args[]) {
// Lambda for addition
FuncInter1 add =
(int x, int y) -> x + y;
// Lambda for multiplication
FuncInter1 multiply =
(int x, int y) -> x * y;
Test tobj = new Test();
System.out.println(
"Addition is " + tobj.operate(6, 3, add)
);
System.out.println(
"Multiplication is " + tobj.operate(6, 3, multiply)
);
// Lambda for single parameter
FuncInter2 fobj = message ->
System.out.println("Hello " + message);
fobj.sayMessage("Geek");
}
}
11. Anonymous Inner Class vs Lambda Expression
| Anonymous Inner Class | Lambda Expression |
|---|---|
| It is a class without a name. | It is a method/function without a name (anonymous function). |
| Can extend abstract and concrete classes. | Cannot extend abstract or concrete classes. |
| Can implement an interface containing any number of abstract methods. | Can implement an interface containing a single abstract method (Functional Interface). |
| Can declare instance variables. | Cannot declare instance variables; declared variables act as local variables according to the notes. |
| Can be instantiated. | Cannot be instantiated. |
this refers to the current anonymous inner-class object. |
this refers to the current outer/enclosing class object. |
| Best choice when multiple methods need to be handled. | Best choice when handling an interface with a single abstract method. |
12. Compilation and Memory Notes
| Anonymous Inner Class | Lambda Expression |
|---|---|
At compilation time, a separate .class file is generated, such as OuterClass$1.class. |
The notes state that no separate dot-class file is generated for a lambda expression and describe it as being converted into a private method of the outer class. |
| Memory is allocated on demand whenever an object is created. | The notes describe it as residing in the permanent memory of the JVM / Method Area. |
13. Zero Parameter Lambda — Complete Example
@FunctionalInterface
interface GreetingService {
void greet();
}
public class LambdaExampleNoParameter {
public static void main(String[] args) {
GreetingService service =
() -> System.out.println("Hello, World!");
service.greet();
}
}
14. Single Parameter Lambda — Complete Example
@FunctionalInterface
interface Printer {
void print(String message);
}
public class LambdaExampleSingleParameter {
public static void main(String[] args) {
Printer printer =
msg -> System.out.println("Message: " + msg);
printer.print("Lambda in Java 8");
}
}
Runnable with Lambda
public class LambdaExpressionExample {
public static void main(String[] args) {
// using Lambda Expression
new Thread(() ->
System.out.println(
"Thread is started: using Lambda Expressions"
)).start();
// old way
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(
"Thread is started: using old method"
);
}
}).start();
}
}
15. Multiple Parameter Lambda — Complete Example
@FunctionalInterface
interface Calculator {
int operate(int a, int b);
}
public class LambdaMultipleParams {
public static void main(String[] args) {
Calculator add =
(a, b) -> a + b;
Calculator subtract =
(a, b) -> a - b;
Calculator multiply =
(a, b) -> a * b;
Calculator divide =
(a, b) -> b != 0 ? a / b : 0;
Calculator mod =
(a, b) -> a % b;
System.out.println(
"Addition: " + add.operate(10, 5)
);
System.out.println(
"Subtraction: " + subtract.operate(10, 5)
);
System.out.println(
"Multiplication: " + multiply.operate(10, 5)
);
System.out.println(
"Division: " + divide.operate(10, 5)
);
System.out.println(
"Mod: " + mod.operate(10, 5)
);
}
}
16. Lambda Expression with Return Value
@FunctionalInterface
interface Adder {
int add(int a, int b);
}
public class LambdaExampleWithReturnValue {
public static void main(String[] args) {
Adder adder =
(a, b) -> a + b;
System.out.println(
"Sum: " + adder.add(10, 20)
);
}
}
(a, b) -> a + b, the expression value acts as the return value.
17. Lambda with Collections
import java.util.Arrays;
public class LambdaExampleWithCollection {
public static void main(String[] args) {
List<String> names =
Arrays.asList(
"Sree",
"Vihas",
"Bhargav",
"Rohith"
);
// Sorting using lambda
Collections.sort(
names,
(s1, s2) -> s1.compareTo(s2)
);
names.forEach(
name -> System.out.println(name)
);
}
}
forEach().
18. Lambda with Runnable
public class LambdaRunnable {
public static void main(String[] args) {
Runnable r = () -> {
for (int i = 0; i < 5; i++) {
System.out.println(
"Running in thread " + i
);
}
};
new Thread(r).start();
}
}
19. Lambda with Callable and ExecutorService
public class LambdaCallableExample {
public static void main(String[] args)
throws Exception {
ExecutorService executor =
Executors.newSingleThreadExecutor();
// Lambda expression implementing Callable
Callable<String> callableTask = () -> {
Thread.sleep(1000);
return "Task completed using Callable with Lambda!";
};
// Submit the task to executor
Future<String> future =
executor.submit(callableTask);
// Get the result of the callable
String result = future.get();
// This will wait until task completes
System.out.println(result);
// Shutdown the executor
executor.shutdown();
}
}
20. Quick Revision
| Topic | Key Point |
|---|---|
| Lambda Expression | Anonymous function introduced in Java 8. |
| Functional Interface | Interface with a single abstract method. |
| Main Purpose | Provide functional-programming benefits and reduce coding. |
| Syntax | (arguments) -> body |
| Zero Parameter | () -> expression |
| Single Parameter | p -> expression or (p) -> expression |
| Multiple Parameters | (p1, p2) -> expression |
| Body | Can contain one or more statements. |
| forEach | Lambda can be used to process collection elements. |
| Runnable | Lambda can provide the Runnable implementation. |
| Callable | Lambda can provide a Callable implementation returning a value. |
| Anonymous Class | Class without a name; can implement interfaces with multiple abstract methods. |
| Lambda | Targets a functional interface with a single abstract method. |
this | Lambda's this refers to the enclosing class according to the notes. |