Lambda Expressions In Java Tutorials
Programming
🔹 Introduction
Lambda Expressions were introduced in Java 8 (1.8).
Before Java 8, Java was purely an Object-Oriented Programming (OOP) language.
From Java 8 onwards, Java also supports Functional Programming concepts.
🔹 OOP vs Functional Programming
OOP Functional Programming
Everything revolves around Classes & Objects Everything revolves around Functions
Methods must be inside classes Functions can be treated as values
Cannot pass methods directly Functions can be passed as arguments
Java introduced Lambda Expressions to enable Functional Programming.
🔷 What is a Lambda Expression?
A Lambda Expression is an anonymous function.
Characteristics:
No name
No access modifier
No return type
No need to explicitly write
return(in single-line expressions)
🔹 Lambda Syntax
java
(parameters) -> { body }🔷 Examples of Lambda Expressions
java
interface test<T>{
abstract String name(T t1);
}
public class Main {
public static void main(String[] args) {
test<String> msg = (name)-> name.toUpperCase();
System.out.println(msg.name("sujal"));
}
}Functional Interface.
An interface that contains exactly one abstract method is called a Functional Interface.
Example:
java
@FunctionalInterface
interface MyInterface {
void m1();
}✔ @FunctionalInterface ensures only one abstract method
✔ If more than one abstract method → compile-time error
🔹 Java 8 introduced several predefined functional interfaces in the:
👉 java.util.function package
🔷 Common Functional Interfaces
Other functional interfaces:
Runnable → run()
Callable → call()
Comparable → compareTo()
🔷 Predicate Functional Interface
Used for conditional checks
Returns boolean
Abstract method:
test(T t)
java
Predicate<Integer> p = i -> i > 10;
System.out.println(p.test(5)); // false
System.out.println(p.test(15)); // true🔹 Task 1: Print names starting with 'A'
java
String[] names = {"Anushka", "Anupama", "Deepika", "Kajol", "Sunny"};
// Predicate<String> result = (name)-> name.toLowerCase().charAt(0) == 'a';
Predicate<String> result = (name)-> name.toLowerCase().startsWith("a");
for (String name : names) {
if (p.test(name)) {
System.out.println(name);
}
}🔹 Task 2: Print persons whose age ≥ 18
java
class Person {
String name;
int age;
Person(String name, int age) {
this.name = name;
this.age = age;
}
}
Predicate<Person> predicate = p -> p.age >= 18;
for (Person person : persons) {
if (predicate.test(person)) {
System.out.println(person.name);
}
}🔷 BiPredicate<T,U>
java
BiPredicate<T,U>
boolean test(T t, U u)✔ Takes 2 inputs
✔ Returns boolean
Example:
java
BiPredicate<Integer, Integer> isSumGreater =
(a, b) -> (a + b) > 50;
System.out.println(isSumGreater.test(30, 25)); // true
System.out.println(isSumGreater.test(10, 20)); // false🔷 Predicate Joining
We can combine multiple predicates using:
and()or()negate()
Example:
java
Predicate<Employee> p1 = e -> e.location.equals("Hyd");
Predicate<Employee> p2 = e -> e.dept.equals("DB");
Predicate<Employee> p3 = e -> e.name.startsWith("A");
Predicate<Employee> finalPredicate = p1.and(p2).and(p3);java
class Person{
int id;
String name;
int age;
String city;
public Person(int id, String name, int age, String city) {
this.id = id;
this.name = name;
this.age = age;
this.city = city;
}
}
public class Main {
public static void main(String[] args) {
ArrayList<Person> arrList = new ArrayList<>();
arrList.add(new Person(101, "anil kumar",30, "jaipur"));
arrList.add(new Person(102, "amit kumar", 40, "delhi"));
arrList.add(new Person(103, "rahul kumar",29,"jaipur"));
arrList.add(new Person(104, "aman kumar",35, "noida"));
arrList.add(new Person(105, "devendra kumar",28,"delhi"));
arrList.add(new Person(106, "lokesh kumar",27,"jaipur"));
arrList.add(new Person(107, "anil kumar",30, "jaipur"));
arrList.add(new Person(108, "amit kumar", 40, "delhi"));
arrList.add(new Person(109, "rahul kumar",29,"jaipur"));
arrList.add(new Person(110, "aman kumar",35, "noida"));
arrList.add(new Person(111, "devendra kumar",28,"delhi"));
arrList.add(new Person(112, "lokesh kumar",27,"jaipur"));
// and() or() negate()
Predicate<Person> ageValue = (person)-> person.age >= 30;
Predicate<Person> nameStart = (person)-> person.name.toLowerCase().startsWith("a");
Predicate<Person> cityValue = (person)-> person.city.toLowerCase() == "jaipur";
// Predicate<Person> result = ageValue.and(nameStart).and(cityValue);
// Predicate<Person> result = ageValue.or(nameStart).or(cityValue);
Predicate<Person> result = ageValue.negate();
// negate() true ko false and false ko true bna ta h
for(Person p : arrList) {
if(result.test(p)) {
System.out.println(p.name);
}
}
}
}🔷 Supplier Functional Interface
Does NOT take input
Returns value
Abstract method:
get()
Example: OTP Generation
java
Supplier<String> s = () -> {
String otp = "";
for (int i = 1; i <= 6; i++) {
otp += (int)(Math.random() * 10);
}
return otp;
};
System.out.println(s.get());🔷 Consumer Functional Interface
Takes input
Returns nothing
Abstract method:
accept(T t)
plaintext
Consumer<String> c = name ->
System.out.println(name + ", Good Evening");
c.accept("Ashok");🔹 forEach() Method
forEach() method takes a Consumer.
java
numbers.forEach(i -> System.out.println(i));🔷 BiConsumer<T,U>
java
BiConsumer<T,U>
void accept(T t, U u)✔ Takes 2 inputs
✔ Returns nothing
Example:
java
BiConsumer<String, Integer> printDetails =
(name, age) -> System.out.println(name + " is " + age + " years old");
printDetails.accept("Anil", 23);Mostly used in Map:
plaintext
Map<String, Integer> map = Map.of("Anil", 23, "Amit", 24);
map.forEach((key, value) ->
System.out.println(key + " -> " + value));forEach() internally uses BiConsumer.
🔷 Function Functional Interface
Takes input
Returns output
Abstract method:
apply(T t)
Correct definition:
plaintext
Function<T, R> {
R apply(T t);
}Example:
plaintext
Function<String, Integer> f = name -> name.length();
System.out.println(f.apply("anilchoudhary"));🔷 BiFunction Example
plaintextCopy
BiFunction<Integer, Integer, Integer> bi = (a, b) -> a + b;
Integer sum = bi.apply(10, 20);
System.out.println(sum);Sorting ArrayList in Descending Order
Without Lambda
java
class NumberComparator implements Comparator<Integer> {
@Override
public int compare(Integer i, Integer j) {
if (i > j) {
return -1;
} else if (i < j) {
return 1;
}
return 0;
}
}Use:
java
Collections.sort(al, new NumberComparator());With Lambda
java
Collections.sort(al, (i, j) -> (i > j) ? -1 : 1);Lambda approach short aur clean hai.
forEach (Consumer c)
forEach() method Java 8 me introduce hua.
Ye Iterable interface me default method hai.
Ye collection ke har element ko traverse karta hai.
Example:
plaintext
ArrayList<Integer> al = new ArrayList<>();
al.add(5);
al.add(3);
al.add(4);
al.add(1);
al.add(2);
al.forEach(i -> System.out.println(i));Internally ye Consumer interface use karta hai.