Stream vs Collection
TL;DR
- Collections are data structures (like
List,Set) used to store and organize data in memory. - Streams are abstractions used to process data declaratively. They do not store data.
- Collections allow multiple iterations; Streams can only be consumed once.
Concept
The best way to understand the difference is a DVD vs an internet video stream.
A Collection is like a DVD. You have all the data downloaded and stored locally. You can skip around, add elements, remove elements, and watch it as many times as you want. It takes up memory based on its size.
A Stream is like a Netflix video stream. The data flows past you. You process it as it arrives. It does not take up permanent storage on your machine. Once the stream finishes playing, you can’t rewind it; you have to request a brand new stream from the server.
Key Differences
| Feature | Collection | Stream |
|---|---|---|
| Storage | Stores data in memory. | Stores no data. It processes data. |
| Iteration | External (Developer writes for loops). | Internal (Stream handles loops internally). |
| Modification | Can add/remove elements. | Cannot modify the underlying source. |
| Reusability | Can be traversed multiple times. | Traversed only once (Single-use). |
| Evaluation | Eager (All elements exist). | Lazy (Elements computed on demand). |
Examples
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
public class StreamVsCollection {
public static void main(String[] args) {
// COLLECTION
List<String> list = new ArrayList<>(List.of("A", "B", "C"));
list.add("D"); // Modifiable
for (String s : list) { System.out.print(s); } // Iteration 1
for (String s : list) { System.out.print(s); } // Iteration 2 (Valid)
System.out.println();
// STREAM
Stream<String> stream = list.stream();
stream.forEach(System.out::print); // Iteration 1 (Consumes the stream)
// stream.forEach(System.out::print); // Iteration 2 (THROWS EXCEPTION!)
}
}
Interview Questions
Q: Why does a Stream throw an exception if reused?
A: Because a Stream is not a data structure, it doesn’t hold data; it merely represents a pipeline of operations applied to a source. Once the terminal operation completes, the data has fully flowed through the pipeline. To traverse again, a new pipeline must be constructed from the source.
Q: What is “Internal Iteration” vs “External Iteration”?
A: In External Iteration (Collections), the developer controls the iteration using a for-each loop or an Iterator. You fetch items one by one.
In Internal Iteration (Streams), the framework controls the iteration. You simply provide the logic (e.g., .forEach(System.out::println)), and the JVM decides how to traverse the data, allowing it to automatically optimize via lazy evaluation or parallel execution.