⬅ Previous Next ➡

Lambda Expressions & Functional Programming

Lambda Expressions & Functional Programming in Java (Streams API, forEach, filter, map, reduce, method references)
  • Lambda Expression is a short way to write an anonymous function in Java (Java 8+).
  • Lambdas work with Functional Interfaces (an interface with exactly one abstract method).
  • Streams API helps process collections in a functional style using operations like filter, map, reduce.

1) Lambda Expressions (Syntax)

  • Basic forms:
  • () -> { }
  • (a) -> a * a
  • (a, b) -> a + b
  • If there is one statement, braces can be omitted.
class LambdaBasicDemo {
    public static void main(String[] args) {

        Runnable r = () -> System.out.println("Running in a thread using lambda");
        new Thread(r).start();

        // Direct lambda
        new Thread(() -> System.out.println("Direct lambda thread")).start();
    }
}

2) Functional Interfaces

  • Must have exactly one abstract method.
  • Use @FunctionalInterface to ensure correctness.
  • Examples: Runnable, Comparator, Callable.
@FunctionalInterface
interface Calculator {
    int add(int a, int b);
}

class FunctionalInterfaceExample {
    public static void main(String[] args) {

        Calculator c = (x, y) -> x + y;
        System.out.println("Sum: " + c.add(10, 20));
    }
}

3) Streams API (Introduction)

  • A Stream is a sequence of elements supporting functional operations.
  • Stream does not store data; it works on collections/arrays.
  • Common flow: source → intermediate ops → terminal op.
import java.util.Arrays;
import java.util.List;

class StreamIntro {
    public static void main(String[] args) {
        List<Integer> nums = Arrays.asList(10, 15, 20, 25);

        long count = nums.stream().count();
        System.out.println("Count: " + count);
    }
}

4) forEach (Terminal Operation)

  • forEach is used to perform action for each element.
  • Can use lambda or method reference.
import java.util.Arrays;
import java.util.List;

class ForEachDemo {
    public static void main(String[] args) {
        List<String> topics = Arrays.asList("Java", "Streams", "Lambda");

        topics.forEach(t -> System.out.println(t));
    }
}

5) filter (Intermediate Operation)

  • filter selects elements based on condition (predicate).
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

class FilterDemo {
    public static void main(String[] args) {
        List<Integer> marks = Arrays.asList(33, 45, 72, 80, 29);

        List<Integer> passed = marks.stream()
                .filter(m -> m >= 40)
                .collect(Collectors.toList());

        System.out.println("Passed: " + passed);
    }
}

6) map (Intermediate Operation)

  • map transforms each element into another form.
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

class MapDemo {
    public static void main(String[] args) {
        List<Integer> nums = Arrays.asList(1, 2, 3, 4);

        List<Integer> squares = nums.stream()
                .map(n -> n * n)
                .collect(Collectors.toList());

        System.out.println("Squares: " + squares);
    }
}

7) reduce (Terminal Operation)

  • reduce combines elements into a single result (sum, max, product).
  • Often used with identity value.
import java.util.Arrays;
import java.util.List;
import java.util.Optional;

class ReduceDemo {
    public static void main(String[] args) {
        List<Integer> nums = Arrays.asList(10, 20, 30);

        int sum = nums.stream().reduce(0, (a, b) -> a + b);
        System.out.println("Sum: " + sum);

        Optional<Integer> max = nums.stream().reduce((a, b) -> a > b ? a : b);
        System.out.println("Max: " + (max.isPresent() ? max.get() : "NA"));
    }
}

8) Method References

  • Method reference is a short form of lambda when calling an existing method.
  • Types:
    • ClassName::staticMethod
    • object::instanceMethod
    • ClassName::new (constructor reference)
import java.util.Arrays;
import java.util.List;

class MethodRefDemo {
    public static void main(String[] args) {
        List<String> list = Arrays.asList("Java", "AI", "Web");

        // Lambda
        list.forEach(x -> System.out.println(x));

        // Method reference
        list.forEach(System.out::println);
    }
}

9) One Combined Example (filter + map + reduce)

  • Example: select passed marks, add bonus +5, then calculate total.
import java.util.Arrays;
import java.util.List;

class CombinedStreamExample {
    public static void main(String[] args) {
        List<Integer> marks = Arrays.asList(33, 45, 72, 80, 29);

        int total = marks.stream()
                .filter(m -> m >= 40)
                .map(m -> m + 5)
                .reduce(0, Integer::sum);

        System.out.println("Total (passed + bonus): " + total);
    }
}

10) Quick Notes

  • Intermediate operations: filter(), map(), sorted() (return Stream).
  • Terminal operations: forEach(), collect(), reduce(), count() (produce result).
  • Streams make code cleaner and reduce loops for data processing.
⬅ Previous Next ➡