Functional Programming
Java's functional side: lambdas, method references, the java.util.function catalog, the Streams API with collectors, and Optional. Interviews lean on this heavily because stream pipelines are now everyday Java and their laziness and parallelism have real gotchas.
part ofJavaoverview, primer and where to startread it →on this pageshowhide
explore
- Functional Concepts in Java6 questions
- Lambdas13 questions
- Lambda Syntax & Typing5 questions
- Lambda Capture & `this`4 questions
- Lambda vs Anonymous Class4 questions
- Method References5 questions
- Method Reference Kinds5 questions
- Functional Interfaces14 questions
- @FunctionalInterface & SAM Rule4 questions
- Built-in Functional Interfaces5 questions
- Function & Predicate Composition5 questions
- Streams API89 questions
- Stream Creation Sources5 questions
- Stream Pipeline Anatomy5 questions
- Stream Laziness & Execution5 questions
- Stateless vs Stateful Operations5 questions
- Short-Circuiting Operations5 questions
- Encounter Order5 questions
- Intermediate Operations6 questions
- map vs flatMap4 questions
- Terminal Operations6 questions
- reduce & Reduction5 questions
- collect & Mutable Reduction5 questions
- Collectors: to Collection/Map5 questions
- Collectors: grouping & partitioning5 questions
- Collectors: downstream & adapters6 questions
- Primitive Streams6 questions
- Parallel Streams5 questions
- Stream Pitfalls6 questions
- Optional15 questions
- Optional Construction & Query5 questions
- Optional Transform & Fallback5 questions
- Optional Anti-patterns5 questions
questions
142 · 6 sectionsHow do Java lambdas and method references implement first-class functions and closures, and what does 'capturing effectively-final locals' mean?
basics
~20 sA lambda is a short way to write a function you can pass around like a value. It can read local variables around it, but only ones that never change after being set (effectively final). A method reference (List::size) is shorthand for a lambda that just calls that method.
What makes the Java Streams API a declarative pipeline, and what do 'lazy' and 'fused' evaluation mean for how a stream actually runs?
basics
~20 sA Stream lets you describe what you want done to a collection (filter, map, then collect) instead of writing loops. The middle steps don't run when you write them; nothing happens until a final step (like collect or count). Then each element is pushed through all the steps at once, not one full pass per step.
How does java.util.function realize function composition, and what do andThen, compose, Predicate.and/or/negate, and Function.identity give you?
basics
~20 sThe java.util.function package has small function types (Function, Predicate, Consumer...) with helper methods that glue functions together: andThen runs another function after this one, compose runs it before, and Predicate has and/or/negate to combine yes/no tests. This lets you build a bigger operation from small reusable ones.
How does Java express immutability with final fields and unmodifiable collections, and why does functional-style code depend on it?
basics
~20 sMark fields final so they can't be reassigned after construction, and use unmodifiable collections (like List.of(...) or List.copyOf(...)) so nobody can add or remove elements. Immutable data can't change under you, which makes functional code and shared/parallel use safe.
Why must lambdas in a parallel stream be pure, stateless, and non-interfering, and what goes wrong if they aren't?
basics
~20 sA parallel stream splits the work across threads. If your lambda changes shared variables or the source collection, multiple threads collide, giving wrong or random results and crashes. So the lambdas must only depend on their input and not change shared state.
What does it mean that a lambda can only capture local variables that are 'effectively final', and why does Java enforce this?
basics
~20 sA lambda can use a local variable only if that variable's value never changes after it is set. 'Effectively final' means you could add the word final and it would still compile. Java forbids changing such captured locals to keep behavior predictable.
What are the syntactic forms a Java lambda expression can take? Show how the parameter list and body vary, and which parts can be omitted.
basics
~20 sA lambda is params -> body. Parameters go on the left, an arrow in the middle, the body on the right. With one parameter you can drop the parentheses; a single-expression body needs no braces or return, while a block body uses { } and an explicit return.
Inside a lambda, what does the `this` reference point to, and how does that differ from `this` inside an anonymous inner class?
basics
~10 sIn a lambda, this means the same thing as in the code around it — the enclosing object. In an anonymous inner class, this means the anonymous object itself, not the surrounding one.
Explain target typing for Java lambdas: why does a lambda have no type on its own, and how does the compiler decide what functional interface it implements?
basics
~20 sA lambda by itself has no fixed type. The compiler looks at the surrounding context — what type is expected there — and matches the lambda to that functional interface. The same x -> x + 1 can be a Function, a UnaryOperator, or your own interface depending on where it's used.
In a Java lambda versus an anonymous inner class, what does the `this` keyword refer to, and why does it differ?
basics
~20 sIn a lambda, this means the enclosing object (the class where the lambda is written). In an anonymous class, this means the anonymous class instance itself. The lambda does not create a new scope for this.
What are the four kinds of method references in Java, and how is each written?
basics
~10 sA method reference is shorthand for a lambda that just calls one method. The four kinds are: static (Class::staticMethod), bound instance (object::method), unbound instance (Class::instanceMethod), and constructor (Class::new).
Explain the difference between a bound and an unbound instance-method reference, including how the receiver is determined in each.
basics
~20 sIn a bound reference (object::method) the object the method runs on is fixed when you write it. In an unbound reference (Class::method) that object is not fixed — it's passed in as the first argument each time the function is called.
How do constructor references (ClassName::new) and array-constructor references (int[]::new) work, and which functional interfaces do they satisfy?
basics
~20 sClassName::new is shorthand for a lambda that calls a constructor — which constructor is picked depends on the target interface's parameters. int[]::new is a special form that creates an array of a given length, like n -> new int[n].
How does the compiler resolve a method reference against a target functional interface, including overload disambiguation and when it fails?
basics
~20 sThe compiler looks at the functional interface the reference must satisfy, then finds a method (or constructor) whose signature is compatible — possibly treating the first parameter as the receiver. If several methods fit equally, or none do, it's a compile error.
When should you choose a method reference over an explicit lambda, and when does a lambda read better or behave differently?
basics
~20 sUse a method reference when the lambda would do nothing but call one existing method with the same arguments. Use a lambda when you need extra logic, to reorder or transform arguments, or when the reference would be ambiguous or unclear.
What are the four core functional interfaces in java.util.function, and what is the shape (inputs and output) of each?
basics
~10 sFunction<T,R> takes one value and returns another. Consumer<T> takes one value, returns nothing. Supplier<T> takes nothing, returns a value. Predicate<T> takes one value, returns a boolean.
In Java, what is the difference between Function.andThen and Function.compose? Given f.andThen(g) versus f.compose(g), which function runs first?
basics
~10 sBoth glue two functions into one. f.andThen(g) runs f first, then feeds its result to g. f.compose(g) runs g first, then feeds its result to f. So andThen reads left-to-right; compose reads right-to-left.
How do you combine Predicates in Java using and, or, and negate, and what do these combinators return?
basics
~10 sPredicate is a function returning true/false. p.and(q) is true only if both are true; p.or(q) is true if either is true; p.negate() flips the result. Each returns a new Predicate you can keep combining.
What is a functional interface in Java, and what does the SAM rule require?
basics
~20 sA functional interface is an interface with exactly one abstract method (the SAM rule, Single Abstract Method). Because there is only one method to implement, you can supply it with a lambda or method reference instead of a full class.
Beyond the four core interfaces, what are the arity-2 variants (BiFunction, BiConsumer, BiPredicate) and the operator specializations (UnaryOperator, BinaryOperator)? How do they relate to the core types?
basics
~20 sThe Bi- versions take two arguments instead of one: BiFunction<T,U,R>, BiConsumer<T,U>, BiPredicate<T,U>. UnaryOperator<T> is a Function whose input and output are the same type; BinaryOperator<T> is a BiFunction with both inputs and output the same type.
What is mutable reduction in the Java Streams API, and how does collect() perform it?
basics
~20 sMutable reduction combines stream elements by adding them into one mutable container (like a List or StringBuilder) instead of creating a new value each step. collect() does this: it makes a container, then drops each element into it.
What is a downstream collector, and how do you use one to count or sum the elements within each group of a groupingBy?
basics
~20 sgroupingBy can take a second collector that runs on each group. So instead of getting lists, you can count items per group with Collectors.counting() or add them up with summingInt(). The result is a Map from key to the computed value.
What does Collectors.groupingBy do, and what is the shape of the result?
basics
~20 sgroupingBy takes a function that maps each element to a key. It returns a Map where each key points to a list of all the elements that produced that key, like sorting items into labeled buckets.
How do you collect a Stream into a List, and what is the difference between Collectors.toList(), Collectors.toUnmodifiableList(), and Stream.toList()?
basics
~10 sUse stream.collect(Collectors.toList()) to get a List. toUnmodifiableList() gives a List you cannot change (add/remove throws). Since Java 16, stream.toList() is a shorter way to get an unmodifiable list.
How does Collectors.toMap(keyMapper, valueMapper) work, and what does each function receive and produce?
basics
~20 stoMap takes two functions: a keyMapper that turns each element into the map key, and a valueMapper that turns each element into the value. The result is a Map built from those keys and values.
What is java.util.Optional intended for, and what is the single most common way developers misuse it?
basics
~20 sOptional is a box that either holds a value or is empty. It is meant to be a method's return type when the result might be absent, so callers must handle the 'nothing' case. The most common misuse is calling get() without first checking that a value is present, which throws if it is empty.
What are the three ways to create an Optional in Java, and when do you use each?
basics
~10 sOptional.of(x) wraps a value you know is not null; Optional.ofNullable(x) wraps a value that might be null and gives empty if it is null; Optional.empty() makes an empty Optional with no value.
What does Optional.get() do when the Optional is empty, and why is calling get() directly discouraged?
basics
~20 sget() returns the value if one is present, but throws NoSuchElementException if the Optional is empty. Calling it directly is risky because you can forget to check first, so prefer orElse, orElseThrow, or ifPresent instead.
How do Optional.map and Optional.flatMap differ, and why does flatMap avoid Optional<Optional<T>>?
basics
~20 smap applies a function and wraps the result in a new Optional. flatMap is used when the function itself already returns an Optional — it flattens the result so you get Optional<T> instead of a nested Optional<Optional<T>>.
What is the difference between Optional.orElse and Optional.orElseGet, and when does it matter?
basics
~20 sorElse takes a ready value and always evaluates it, even when the Optional has a value. orElseGet takes a function that produces the fallback only when the Optional is empty. Use orElseGet when the fallback is expensive.