Java 8 Interview Questions: Streams, Lambdas and Optional Explained (2026)

By Preeti Verma

Java 8 shipped in 2014, yet it is still the part of Java that interviewers lean on most. The reason is simple: almost every Java codebase uses streams, lambdas and Optional, so the questions quickly show whether you use them well or only copy them from examples.

This guide covers the Java 8 questions that come up again and again, what a good answer includes, and the mistakes that cost candidates marks. Say each answer out loud as you read. That is how it will come out in the interview.

1. What is a lambda expression, and what is a functional interface?

A lambda is a short way to write an implementation of an interface that has exactly one abstract method. That kind of interface is called a functional interface. You can mark one with @FunctionalInterface, which makes the compiler reject a second abstract method.

Know these four by heart, because they appear in almost every answer:

  • Predicate<T>: takes a value, returns a boolean (for filtering).
  • Function<T, R>: takes a value, returns another value (for mapping).
  • Consumer<T>: takes a value, returns nothing (for side effects such as printing).
  • Supplier<T>: takes nothing, returns a value (for lazy creation).

A strong answer adds that a lambda is not just a shorter anonymous class. It does not create a new scope for this: inside a lambda, this means the enclosing class, while inside an anonymous class it means the anonymous object.

2. What is a method reference?

It is a shorthand for a lambda that only calls an existing method. String::length replaces s -> s.length(), and System.out::println replaces x -> System.out.println(x). There are four forms: a static method, a method on a particular object, a method on any object of a type, and a constructor (ArrayList::new). Interviewers mostly want to hear that you use it when it makes the code clearer, not everywhere.

3. Streams vs collections

A collection stores data. A stream describes a computation over data and does not store anything. Three points matter:

  • Streams are lazy. Intermediate operations such as filter and map do nothing until a terminal operation such as collect, forEach or count runs.
  • A stream can be used once. Reuse it and you get an IllegalStateException.
  • Streams do not change the source. They produce a new result.

The classic trap question: "You wrote a stream pipeline and nothing happens. Why?" The answer is that there is no terminal operation.

4. map vs flatMap

map transforms each element into exactly one new element. flatMap transforms each element into a stream of zero or more elements and then flattens all of them into one stream.

Give an example. If you have a List<Order> and each order has a List<Item>, orders.stream().map(Order::getItems) gives you a stream of lists. orders.stream().flatMap(o -> o.getItems().stream()) gives you one stream of items. That single sentence, with the example, is usually enough.

5. Intermediate vs terminal operations

Intermediate operations return a stream and are lazy: filter, map, flatMap, sorted, distinct, limit, peek. Terminal operations produce a result or a side effect and end the pipeline: collect, forEach, reduce, count, findFirst, anyMatch.

Short-circuiting is a good follow-up. findFirst, anyMatch and limit can stop early, so they work even on infinite streams such as Stream.iterate.

6. Collectors: groupingBy, partitioningBy and toMap

Expect a small coding question such as "group employees by department and count them":

Map<String, Long> countByDept = employees.stream()
    .collect(Collectors.groupingBy(Employee::getDepartment, Collectors.counting()));

Know the difference: groupingBy makes any number of groups, partitioningBy always makes exactly two (true and false), and toMap throws an IllegalStateException on a duplicate key unless you pass a merge function. That last detail catches many people.

7. Parallel streams: when are they a bad idea?

A parallel stream splits the work across the common ForkJoinPool. It can help for CPU-heavy work on large data. It can hurt when:

  • The data is small, because splitting costs more than it saves.
  • The work blocks on I/O, because it ties up threads shared with the rest of the JVM.
  • The operation depends on order or shared mutable state.

A good answer says you would measure first and would not use a parallel stream in a web request path without thinking about the shared pool.

8. Optional: what it is for and how it is misused

Optional<T> is a return type that says "there may be no value here". Use map, flatMap, orElse, orElseGet and orElseThrow instead of calling get().

Points that show depth:

  • orElse(x) always evaluates x, even when a value is present. orElseGet(() -> x) only evaluates it when needed. Use orElseGet when creating the fallback is expensive.
  • Do not use Optional for fields, method parameters or collections. Return an empty collection instead of an Optional<List<T>>.
  • Optional.of(null) throws. Use Optional.ofNullable.

9. Default and static methods in interfaces

Java 8 added default methods so interfaces could gain new methods without breaking every implementing class (that is how stream() was added to Collection). If a class inherits the same default method from two interfaces, it must override it and can choose one with InterfaceName.super.method(). This is the Java 8 version of the diamond problem, and interviewers like it.

10. The new Date and Time API

java.time (LocalDate, LocalDateTime, ZonedDateTime, Duration, Period) replaced the old Date and Calendar. The key points are that the new types are immutable and thread-safe, and that SimpleDateFormat is not thread-safe while DateTimeFormatter is.

Tricky stream questions to practise

  1. Find the second highest salary using streams.
  2. Find the first non-repeating character in a string.
  3. Convert a list of strings to a map of string to length, handling duplicates.
  4. Flatten a list of lists and remove duplicates while keeping order.
  5. Why can you not modify a local variable inside a lambda? (It must be effectively final.)

How to practise

Reading is the slowest way to learn this. Write each answer on a blank editor without autocomplete, then say the explanation out loud as if the interviewer asked a follow-up. Our Core Java question bank has scenario-style questions with a free preview, and a mock interview lets you answer out loud and get follow-ups. For a wider list of what experienced candidates are asked, read Core Java interview questions for experienced developers.

FAQ

Are Java 8 questions still asked if the company uses Java 17 or 21? Yes. Streams, lambdas and Optional are the base, and newer features (records, sealed classes, text blocks, pattern matching) are usually asked on top of them.

Is it enough to know the syntax? No. Interviewers ask why: why a stream is lazy, why toMap can fail, why orElse can be wasteful. Prepare the reason behind each rule.

The takeaway

Know the four core functional interfaces, how laziness works, the difference between map and flatMap, and the few classic traps (duplicate keys in toMap, orElse vs orElseGet, parallel streams on small data). Answer each in two or three clear sentences with a tiny example, and you will sound like someone who uses Java 8 every day.