HuntExams Academy logo
JavaIntermediate#java8#streams

Explain Java 8 Streams.

Answer

Streams provide a functional-style pipeline of operations (filter, map, reduce, collect) on collections. Intermediate ops are lazy, terminal ops trigger execution. They support parallel streams for multi-core processing.

Example

List<String> names = List.of("Amit","Bob","Ankit");
List<String> result = names.stream()
  .filter(n -> n.startsWith("A"))
  .map(String::toUpperCase)
  .collect(Collectors.toList());
// [AMIT, ANKIT]

Detailed explanation

Java 8 Streams provide a declarative, functional-style way to process sequences of elements from collections, arrays, or generated sources. Instead of writing a loop that specifies every processing step, you describe transformations and the result you need. A stream is not a collection: it does not store elements, and its operations generally do not modify the source. Streams matter because they make filtering, transformation, grouping, and aggregation easier to express, while separating processing logic from explicit iteration.

A stream pipeline has a source, zero or more intermediate operations, and a terminal operation. Intermediate operations such as filter, map, sorted, and distinct return streams and are lazy: declaring them does not immediately process elements. A terminal operation such as collect, reduce, count, or forEach initiates processing. Internally, streams use source traversal machinery, including Spliterator, and can combine stages so an element passes through several operations without creating intermediate collections. Short-circuiting operations such as findFirst and anyMatch can finish without consuming the entire source; stateful operations such as sorted may require buffering elements.

For the example, use Arrays.asList("Amit", "Bob", "Ankit") when targeting Java 8, because List.of was introduced in Java 9. Calling names.stream().filter(n -> n.startsWith("A")).map(String::toUpperCase).collect(Collectors.toList()) produces [AMIT, ANKIT]. Here, filter retains matching names, map transforms each retained name, and collect accumulates the results into a list. For predictable, locale-independent casing, use n -> n.toUpperCase(Locale.ROOT). A reduction instead combines elements into a summary, such as a total using reduce(0, Integer::sum). A consumed stream cannot be reused; obtain another stream from the source for another pipeline.

Parallel streams split work into tasks, generally using the common ForkJoinPool, and combine partial results. They can exploit multiple cores, but are not automatically faster: task overhead, source splitting, workload size, ordering constraints, and shared-state contention matter. Interviewers look for an understanding of laziness, terminal operations, single-use streams, and safe parallel execution. Prefer stateless, non-interfering functions, avoid modifying the source during traversal, and use associative reductions so parallel combinations remain correct.

Key points to remember

  • A stream processes elements from a source; it does not store them.
  • Intermediate operations are lazy; terminal operations initiate processing.
  • filter selects elements, map transforms them, and collect or reduce produces a result.
  • Streams are single-use, and short-circuiting operations may avoid full traversal.
  • Parallel streams need suitable workloads and safe operations; measure before choosing them.

Common mistakes candidates make

  • Using List.of in a Java 8 example, although it was introduced in Java 9.
  • Expecting intermediate operations to execute immediately or trying to reuse a consumed stream.
  • Assuming parallel streams always improve performance or mutating shared collections inside parallel operations.

Likely follow-up questions

What is the difference between map and flatMap?

map transforms each input element into one output element, which may itself be a collection or stream. flatMap transforms each element into a stream and flattens those streams, for example converting a list of lists into one stream of values.

How do collect and reduce differ?

reduce combines elements into a result using an associative operation, such as summing integers. collect supports mutable reduction through a supplier, accumulator, and combiner, making it suitable for building lists, maps, and grouped results.

When should you use a parallel stream?

Consider it for sufficiently large, easily partitioned, CPU-bound workloads with independent operations and associative reductions. Benchmark against a sequential stream, and be cautious with blocking I/O or shared mutable state because these can undermine performance or correctness.

Interview tip: Explain source, lazy intermediate operations, and terminal execution using the example, then mention single-use streams and the limitations of parallel processing.

Related Interview Questions

1
JavaIntermediate#java8#lambda

What are lambda expressions?

Open
2
JavaIntermediate#java8

What is a functional interface?

Open
3
JavaIntermediate#java8

What is Optional?

Open