What are Streams in Java 8?
Learn what Java 8 Streams are, how the source, intermediate and terminal pipeline works, lazy evaluation, parallel streams and code examples.
Expected Interview Answer
A Stream in Java 8 is a sequence of elements from a source (like a collection or array) that supports declarative, pipelined operations such as filter, map, and reduce to process data without mutating the source.
A stream pipeline has three parts: a source, zero or more lazy intermediate operations (filter, map, sorted) that return a new stream, and a single terminal operation (collect, forEach, reduce, count) that triggers execution. Streams are lazy, can be sequential or parallel, and are consumed once — you cannot reuse a stream after a terminal operation runs. They express what to compute rather than the loop mechanics of how to compute it.
- Concise, readable declarative code
- Lazy evaluation avoids unnecessary work
- Easy parallelism with parallelStream()
- Composable pipeline of operations
- Encourages immutability, no source mutation
AI Mentor Explanation
Think of a stream as a bowling machine feeding one ball at a time to a batting drill. You attach filters — only yorkers, then only those on off stump — and each ball passes through the chain lazily. The scoreboard tallies runs only when the innings ends, just as a terminal operation triggers the whole pipeline and produces the final result.
Step-by-Step Explanation
Step 1
Get a source
Obtain a stream from a collection via list.stream(), Arrays.stream(arr), or Stream.of(...).
Step 2
Chain intermediate ops
Apply lazy transformations like filter(), map(), sorted() that each return a new stream.
Step 3
Add a terminal op
Finish with collect(), forEach(), reduce(), or count() to trigger the pipeline.
Step 4
Collect results
Use Collectors (toList, groupingBy, joining) to gather output into a concrete structure.
Step 5
Consider parallelism
Switch to parallelStream() for CPU-bound work on large data when order is not required.
What Interviewer Expects
- Definition of a stream and its pipeline structure
- Difference between intermediate and terminal operations
- Understanding of lazy evaluation
- Streams do not mutate the source and are consumed once
- Awareness of sequential vs parallel streams
Common Mistakes
- Confusing streams with collections that store data
- Reusing a stream after a terminal operation (throws IllegalStateException)
- Thinking intermediate operations execute immediately
- Assuming parallelStream is always faster
- Forgetting a terminal operation, so nothing runs
Best Answer (HR Friendly)
“Streams in Java 8 let you process a collection of data by describing the steps — like filtering and transforming — instead of writing manual loops. The work only actually happens at the final step, which keeps the code short, readable, and easy to run in parallel.”
Code Example
import java.util.List;
import java.util.stream.Collectors;
public class StreamDemo {
public static void main(String[] args) {
List<String> names = List.of("Anil", "Bhavya", "Chandra", "Deepa");
List<String> result = names.stream()
.filter(n -> n.length() > 4) // intermediate: keep long names
.map(String::toUpperCase) // intermediate: transform
.sorted() // intermediate: order
.collect(Collectors.toList()); // terminal: trigger pipeline
System.out.println(result); // [BHAVYA, CHANDRA]
}
}Follow-up Questions
- What is the difference between intermediate and terminal operations?
- How does lazy evaluation work in streams?
- When would you use parallelStream and what are its risks?
- What is the difference between map() and flatMap()?
- Why can a stream not be reused after a terminal operation?
MCQ Practice
1. Which of these is a terminal operation on a Stream?
collect() is terminal — it triggers the pipeline; filter, map and sorted are lazy intermediate operations.
2. What happens if you call a terminal operation twice on the same stream?
A stream is consumed once; reusing it after a terminal operation throws IllegalStateException: stream has already been operated upon or closed.
3. Intermediate stream operations are best described as?
Intermediate operations are lazy: they build the pipeline but only execute when a terminal operation runs.
Flash Cards
What are the three parts of a stream pipeline? — A source, zero or more lazy intermediate operations, and one terminal operation.
Are streams eager or lazy? — Intermediate operations are lazy; nothing runs until a terminal operation is invoked.
Can a stream be reused? — No. After a terminal operation the stream is consumed; reusing it throws IllegalStateException.
How do you get a parallel stream? — Call collection.parallelStream() or stream().parallel().