Last updated : July 27, 2026

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.

Job PortalJobs