Stream API in Java
The Stream API in Java, in the java.util.stream package, is used to process a sequence of elements such as a list of names or numbers. A stream lets you describe what you want, such as "keep the students who passed, take their names, sort them", as a chain of operations called a pipeline, instead of writing loops that say how to do it step by step. Streams were added in Java 8 and are now the standard way to filter, transform and summarize collections. In this lesson, you will learn what a stream is, its features and the parts of a pipeline.
What Is a Stream?
A stream is not a collection. It doesn't store elements. It carries elements from a source, such as a list, through a series of operations, and produces a result. Think of it as a conveyor belt in a factory: items come from a store room, pass through machines that check and change them, and arrive at a packing station.
Parts of a Stream Pipeline
| Part | What it does | Examples |
|---|---|---|
| Source | It is used to supply the elements. | list.stream(), Arrays.stream(arr), Stream.of(...) |
| Intermediate operations | They transform the stream and return a new stream. | filter, map, sorted, distinct, limit |
| Terminal operation | It produces the result and ends the stream. | toList, collect, forEach, count, sum, reduce |
Features of Streams
- No storage: a stream holds no data of its own.
- Doesn't change the source: filtering a stream never removes anything from the original list.
- Lazy: intermediate operations do nothing until a terminal operation runs.
- Single use: once a terminal operation runs, the stream is used up and can't be reused.
- Can be parallel:
parallelStream()can split the work across CPU cores.
Example: A First Pipeline
Let's see an example that lists the names of students who passed, in alphabetical order.
import java.util.List;
public class FirstStream {
record Student(String name, int marks) { }
public static void main(String[] args) {
List<Student> students = List.of(
new Student("Srihitha", 78),
new Student("Navika", 91),
new Student("Anamaneni", 38),
new Student("Advitha", 85));
List<String> passed = students.stream()
.filter(s -> s.marks() >= 50)
.map(Student::name)
.sorted()
.toList();
System.out.println("Passed: " + passed);
System.out.println("Original size: " + students.size());
}
}Passed: [Advitha, Navika, Srihitha]
Original size: 4Explanation:
students.stream()is the source.filterkeeps students with at least 50 marks, so Anamaneni (38) is dropped.map(Student::name)turns each student into a name.sorted()orders the names, andtoList()is the terminal operation that collects them into a new list.- The original list still has 4 students; streams never change their source.
Example: A Stream Can Be Used Only Once
import java.util.List;
import java.util.stream.Stream;
public class OnceOnly {
public static void main(String[] args) {
Stream<String> names = List.of("Navika", "Srihitha").stream();
System.out.println(names.count());
try {
names.count();
} catch (IllegalStateException e) {
System.out.println(e.getMessage());
}
}
}2
stream has already been operated upon or closedExplanation: The first count() consumed the stream. Calling another terminal operation on the same stream throws IllegalStateException. To process the data again, create a new stream from the source.
Stream vs Collection
| Collection | Stream | |
|---|---|---|
| Purpose | Stores data | Processes data |
| Elements | Kept in memory | Computed on demand |
| Can be changed | Yes (add, remove) | No; it produces new results |
| Traversal | Many times | Once |
| Iteration | External (you write the loop) | Internal (the stream loops for you) |
Common Mistakes
Expecting filter to remove elements from the original list. Use removeIf to change the list.
Storing a stream in a variable and using it twice. Create a new stream each time.
Forgetting the terminal operation. Without it, nothing runs.
Interview Corner
What is a stream in Java, and how is it different from a collection?
A stream, from java.util.stream, is a sequence of elements that supports a pipeline of operations, such as filter, map and collect, over a source like a collection or array. Unlike a collection, it doesn't store elements, doesn't modify its source, computes elements lazily only when a terminal operation runs, can be traversed only once, and iterates internally. Collections store data; streams describe computations on data.
Practice
- Easy: From a list of numbers, use a stream to make a list of the squares of the numbers greater than 10.
- Harder: From a list of words, produce a sorted list of the distinct words with more than four letters, in upper case.
Key Takeaways
Was this tutorial helpful?