Matheion

MA-JAVA0 · Module 21

Lambdas, anonymous classes, and functional interfaces

Topics: Functional interface · Lambda · Anonymous class · Comparator

Overview

Session 21 — Lambdas, anonymous classes, and functional interfaces

Java 8 added lambda expressions—compact syntax for a block of code passed where a functional interface (one abstract method) is expected. Older code used anonymous classes for the same job. This session ties lambdas to Comparator, Runnable, event-style callbacks, and the @FunctionalInterface safeguard.

Time: about 95 minutes.

Concepts

1. Functional interfaces

A functional interface has exactly one abstract method (default methods on interfaces do not count toward that limit). Annotate with @FunctionalInterface so accidental second abstract methods become compile errors.

@FunctionalInterface
public interface IntPredicate {
    boolean test(int value);
}

2. Lambda syntax

Parameters, arrow, body:

IntPredicate positive = v -> v > 0;

Multi-statement bodies use braces and explicit return:

IntPredicate noisyPositive = v -> {
    boolean ok = v > 0;
    return ok;
};

Types are often inferred from the target interface.


3. Anonymous classes (pre-lambda style)

Runnable task = new Runnable() {
    @Override
    public void run() {
        System.out.println("from anonymous");
    }
};

Still useful when you need multiple methods (rare with interfaces) or heavy per-instance setup—otherwise prefer lambdas for readability.


4. Variable capture

Lambdas may read effectively final locals from the enclosing scope:

String prefix = "[job]";
Runnable r = () -> System.out.println(prefix + " start");

You cannot mutate prefix after capture—compiler enforces effectively final rules.


5. Method references (preview)

When a lambda only forwards to an existing method, String::length or Objects::nonNull shorthand may apply—same functional interface target, terser syntax.


6. Comparator composition

import java.util.Comparator;

Comparator<String> byLen = Comparator.comparing(String::length);
Comparator<String> byLenThenLex = byLen.thenComparing(Comparator.naturalOrder());

Readable sorting keys beat hand-written compareTo chains.


7. Pitfalls

  • Passing a lambda where the target type is ambiguous—add explicit cast to the functional interface or assign to a typed variable.
  • Heavy work inside lambdas passed to parallel streams—side effects and contention surprise beginners (defer parallel streams until advanced material).
  • Using lambdas where a named private method reads clearer—brevity is not always clarity.

Examples

Example A — sort with lambda

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

public class SortDemo {
    public static void main(String[] args) {
        List<String> items = new ArrayList<>(List.of("delta", "alpha", "charlie"));
        items.sort((a, b) -> Integer.compare(a.length(), b.length()));
        System.out.println(items);
    }
}

Better style replaces the lambda with Comparator.comparing(String::length) once you recognise the pattern.


Example B — anonymous FilenameFilter (classic API)

import java.io.File;
import java.io.FilenameFilter;

public class PickTxt {
    public static String[] txtOnly(File dir) {
        return dir.list(new FilenameFilter() {
            @Override
            public boolean accept(File d, String name) {
                return name.endsWith(".txt");
            }
        });
    }
}

Modern code might use Files.newDirectoryStream with lambdas, but the anonymous class shows the implements-on-the-fly shape clearly.


Example C — capture of an effectively final local

public class Greeter {
    public static Runnable forUser(String name) {
        String msg = "Hello, " + name; // effectively final
        return () -> System.out.println(msg);
    }
}

The lambda closes over msg; reassigning msg after initialization would be a compile error because the lambda needs a stable snapshot.

Practice check — lambdas and functional interfaces

Multiple-choice check from the Matheion app lesson. Pick an answer for each question, then submit.

  1. 1.A functional interface is…

  2. 2.Which is a lambda that returns whether `n` is positive?

  3. 3.An anonymous class can…

  4. 4.`Comparator<String>` is often implemented with a lambda because…

  5. 5.Lambdas can capture local variables only if those variables are…