Detailed explanation
Lambda expressions, introduced in Java 8, provide concise syntax for supplying the implementation of a functional interface: an interface with exactly one abstract method, excluding methods matching public methods of Object. Default and static methods do not count towards this requirement. A lambda represents behaviour that can be passed to a method, stored in a variable, or executed later. This makes callbacks, sorting rules, and collection processing easier to express without the boilerplate of an anonymous class.
The syntax is (parameters) -> expression or (parameters) -> { statements; }. For example, Runnable r = () -> System.out.println("running"); implements Runnable.run(), which takes no arguments and returns nothing. Comparator<String> byLength = (a, b) -> Integer.compare(a.length(), b.length()); implements compare(String, String). Java infers parameter types from the target functional interface. The expression (a, b) -> a + b therefore needs a compatible target type, such as IntBinaryOperator. For a value-returning block body, use an explicit return statement; an expression body supplies its result directly.
Under the hood, a lambda is not simply compiled as an anonymous inner class. Java compilers typically use an invokedynamic call site and runtime machinery to produce an implementation of the target interface. Allocation and instance reuse are implementation details, so code should not depend on lambda object identity. Creating a lambda does not execute its body: r.run() invokes the Runnable above. Lambdas can capture local variables only when they are final or effectively final, meaning they are not reassigned. Unlike an anonymous class, a lambda uses this from its enclosing context.
Lambdas matter because APIs such as Stream.filter, Stream.map, List.sort, and Iterable.forEach accept functional interfaces. They let developers describe a condition, transformation, or action where it is needed. In interviews, demonstrate the syntax, identify the target interface and its abstract method, and explain type inference and variable capture. Also clarify that lambdas do not automatically introduce parallelism or guarantee faster execution; their main benefit is expressing behaviour clearly and composably.
Key points to remember
- A lambda supplies behaviour for a functional interface with one abstract method.
- Its syntax is (parameters) -> expression or (parameters) -> { statements; }.
- The target interface determines parameter types, return requirements, and permitted checked exceptions.
- Captured local variables must be final or effectively final; this refers to the enclosing context.
- Lambdas are widely used with Streams, collection operations, comparators, and callbacks.
Common mistakes candidates make
- Treating a lambda as an independently typed function without a compatible target functional interface.
- Reassigning a captured local variable or assuming effectively final makes the referenced object immutable.
- Using subtraction in general-purpose numeric comparators, which can overflow; prefer Integer.compare or comparator factory methods.
Likely follow-up questions
Is @FunctionalInterface mandatory?
No; an interface qualifies through its abstract-method structure, even without the annotation. The annotation asks the compiler to validate that the interface satisfies the functional-interface contract.
How is a lambda different from an anonymous class?
A lambda targets a functional interface, while an anonymous class can also extend a class and declare additional members. A lambda inherits the enclosing meaning of this; an anonymous class has its own this.
What is the relationship between lambdas and method references?
A method reference is a compact alternative when a lambda only delegates to an existing compatible method, such as System.out::println. Both require a target functional interface; for length-based sorting, Comparator.comparingInt(String::length) is an idiomatic option.
Interview tip: Start with the functional-interface definition, explain the Runnable example, and finish with one practical use and the effectively-final capture rule.
