skip to content

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 pageshow

explore

questions

142 · 6 sections

How do Java lambdas and method references implement first-class functions and closures, and what does 'capturing effectively-final locals' mean?

level: juniorimportance: must knowfreq 78%
basics
~20 s

A 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.

open as a page

What makes the Java Streams API a declarative pipeline, and what do 'lazy' and 'fused' evaluation mean for how a stream actually runs?

level: middleimportance: must knowfreq 80%
basics
~20 s

A 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.

open as a page

How does java.util.function realize function composition, and what do andThen, compose, Predicate.and/or/negate, and Function.identity give you?

level: middleimportance: should knowfreq 58%
basics
~20 s

The 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.

open as a page

How does Java express immutability with final fields and unmodifiable collections, and why does functional-style code depend on it?

level: middleimportance: should knowfreq 55%
basics
~20 s

Mark 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.

open as a page

Why must lambdas in a parallel stream be pure, stateless, and non-interfering, and what goes wrong if they aren't?

level: seniorimportance: should knowfreq 48%
basics
~20 s

A 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.

open as a page

What does it mean that a lambda can only capture local variables that are 'effectively final', and why does Java enforce this?

level: juniorimportance: must knowfreq 70%
basics
~20 s

A 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.

open as a page

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.

level: juniorimportance: must knowfreq 78%
basics
~20 s

A 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.

open as a page

Inside a lambda, what does the `this` reference point to, and how does that differ from `this` inside an anonymous inner class?

level: middleimportance: must knowfreq 65%
basics
~10 s

In 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.

open as a page

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?

level: middleimportance: must knowfreq 72%
basics
~20 s

A 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.

open as a page

In a Java lambda versus an anonymous inner class, what does the `this` keyword refer to, and why does it differ?

level: middleimportance: must knowfreq 78%
basics
~20 s

In 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.

open as a page

What are the four kinds of method references in Java, and how is each written?

level: juniorimportance: must knowfreq 72%
basics
~10 s

A 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).

open as a page

Explain the difference between a bound and an unbound instance-method reference, including how the receiver is determined in each.

level: middleimportance: must knowfreq 68%
basics
~20 s

In 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.

open as a page

How do constructor references (ClassName::new) and array-constructor references (int[]::new) work, and which functional interfaces do they satisfy?

level: middleimportance: should knowfreq 55%
basics
~20 s

ClassName::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].

open as a page

How does the compiler resolve a method reference against a target functional interface, including overload disambiguation and when it fails?

level: seniorimportance: should knowfreq 42%
basics
~20 s

The 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.

open as a page

When should you choose a method reference over an explicit lambda, and when does a lambda read better or behave differently?

level: seniorimportance: nice to knowfreq 30%
basics
~20 s

Use 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.

open as a page

What are the four core functional interfaces in java.util.function, and what is the shape (inputs and output) of each?

level: juniorimportance: must knowfreq 80%
basics
~10 s

Function<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.

open as a page

In Java, what is the difference between Function.andThen and Function.compose? Given f.andThen(g) versus f.compose(g), which function runs first?

level: juniorimportance: must knowfreq 70%
basics
~10 s

Both 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.

open as a page

How do you combine Predicates in Java using and, or, and negate, and what do these combinators return?

level: juniorimportance: must knowfreq 65%
basics
~10 s

Predicate 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.

open as a page

What is a functional interface in Java, and what does the SAM rule require?

level: juniorimportance: must knowfreq 78%
basics
~20 s

A 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.

open as a page

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?

level: middleimportance: should knowfreq 62%
basics
~20 s

The 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.

open as a page

What is mutable reduction in the Java Streams API, and how does collect() perform it?

level: juniorimportance: must knowfreq 70%
basics
~20 s

Mutable 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.

open as a page

What is a downstream collector, and how do you use one to count or sum the elements within each group of a groupingBy?

level: juniorimportance: must knowfreq 72%
basics
~20 s

groupingBy 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.

open as a page

What does Collectors.groupingBy do, and what is the shape of the result?

level: juniorimportance: must knowfreq 78%
basics
~20 s

groupingBy 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.

open as a page

How do you collect a Stream into a List, and what is the difference between Collectors.toList(), Collectors.toUnmodifiableList(), and Stream.toList()?

level: juniorimportance: must knowfreq 72%
basics
~10 s

Use 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.

open as a page

How does Collectors.toMap(keyMapper, valueMapper) work, and what does each function receive and produce?

level: juniorimportance: must knowfreq 68%
basics
~20 s

toMap 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.

open as a page

What is java.util.Optional intended for, and what is the single most common way developers misuse it?

level: juniorimportance: must knowfreq 70%
basics
~20 s

Optional 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.

open as a page

What are the three ways to create an Optional in Java, and when do you use each?

level: juniorimportance: must knowfreq 78%
basics
~10 s

Optional.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.

open as a page

What does Optional.get() do when the Optional is empty, and why is calling get() directly discouraged?

level: middleimportance: must knowfreq 70%
basics
~20 s

get() 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.

open as a page

How do Optional.map and Optional.flatMap differ, and why does flatMap avoid Optional<Optional<T>>?

level: middleimportance: must knowfreq 74%
basics
~20 s

map 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>>.

open as a page

What is the difference between Optional.orElse and Optional.orElseGet, and when does it matter?

level: middleimportance: must knowfreq 78%
basics
~20 s

orElse 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.

open as a page