The Streams API enables functional-style operations on collections. Streams are lazy — intermediate operations are not executed until a terminal operation is called. Combined with lambda expressions, streams replace most explicit for-loops in modern Java.
Import: import java.util.stream.*; | Docs: Oracle JavaDoc
| Name | Signature | Description |
|---|---|---|
| stream() | default Stream<E> stream() | Return sequential stream from Collection |
| Stream.of | static <T> Stream<T> of(T... values) | Create stream from values |
| Stream.generate | static <T> Stream<T> generate(Supplier<T> s) | Create infinite stream from Supplier |
| Stream.iterate | static <T> Stream<T> iterate(T seed, UnaryOperator<T> f) | Create infinite iterated stream |
| filter | Stream<T> filter(Predicate<? super T> pred) | Keep elements matching predicate |
| map | Stream<R> map(Function<? super T,? extends R> f) | Transform each element |
| mapToInt | IntStream mapToInt(ToIntFunction<? super T> f) | Map to IntStream for sum/avg/etc. |
| flatMap | Stream<R> flatMap(Function<? super T, Stream<R>> f) | Map each element to stream and flatten |
| distinct | Stream<T> distinct() | Remove duplicate elements |
| sorted | Stream<T> sorted() | Sort using natural ordering |
| sorted(Comparator) | Stream<T> sorted(Comparator<? super T> c) | Sort with comparator |
| limit | Stream<T> limit(long maxSize) | Truncate stream to maxSize elements |
| skip | Stream<T> skip(long n) | Skip first n elements |
| peek | Stream<T> peek(Consumer<? super T> action) | Perform action on each element (for debug) |
| forEach | void forEach(Consumer<? super T> action) | Terminal: perform action on each element |
| collect | R collect(Collector<? super T,A,R> collector) | Terminal: accumulate into collection |
| Collectors.toList | static <T> Collector<T,?,List<T>> toList() | Collect stream to List |
| Collectors.toSet | static <T> Collector<T,?,Set<T>> toSet() | Collect stream to Set |
| Collectors.joining | static Collector joining(CharSequence delim) | Join strings with delimiter |
| Collectors.groupingBy | static Collector groupingBy(Function classifier) | Group elements by classifier function |
| Collectors.counting | static <T> Collector<T,?,Long> counting() | Count elements in each group |
| count | long count() | Terminal: return element count |
| sum / average | int sum() / OptionalDouble average() | Terminal on IntStream/LongStream/DoubleStream |
| findFirst | Optional<T> findFirst() | Terminal: return first element |
| anyMatch | boolean anyMatch(Predicate<? super T> pred) | Terminal: true if any element matches |
| allMatch | boolean allMatch(Predicate<? super T> pred) | Terminal: true if all elements match |
| noneMatch | boolean noneMatch(Predicate<? super T> pred) | Terminal: true if no elements match |
| reduce | Optional<T> reduce(BinaryOperator<T> acc) | Terminal: combine elements with accumulator |
| min / max | Optional<T> min/max(Comparator<? super T> c) | Terminal: find minimum/maximum element |
| toArray | Object[] toArray() | Terminal: collect elements into array |
Save as ClassName.java (matching the public class name), compile with javac ClassName.java, run with java ClassName.
import java.util.*;
import java.util.stream.*;
public class StreamsDemo {
record Student(String name, String major, int score) {}
public static void main(String[] args) {
List<Student> students = List.of(
new Student("Alice", "CS", 95),
new Student("Bob", "Math", 87),
new Student("Carol", "CS", 92),
new Student("Dave", "Math", 78),
new Student("Eve", "CS", 88),
new Student("Frank", "Math", 91)
);
// Filter + map + collect
List<String> csTopStudents = students.stream()
.filter(s -> s.major().equals("CS") && s.score() >= 90)
.map(Student::name)
.sorted()
.collect(Collectors.toList());
System.out.println("CS top students: " + csTopStudents);
// groupingBy major → average score
Map<String, Double> avgByMajor = students.stream()
.collect(Collectors.groupingBy(Student::major,
Collectors.averagingInt(Student::score)));
avgByMajor.forEach((major, avg) ->
System.out.printf(" %-6s avg=%.2f%n", major, avg));
// Statistics
IntSummaryStatistics stats = students.stream()
.mapToInt(Student::score)
.summaryStatistics();
System.out.printf("Min=%d Max=%d Avg=%.2f%n",
stats.getMin(), stats.getMax(), stats.getAverage());
// Joining
String roster = students.stream()
.sorted(Comparator.comparingInt(Student::score).reversed())
.map(s -> s.name() + "(" + s.score() + ")")
.collect(Collectors.joining(", "));
System.out.println("Roster: " + roster);
// FlatMap — all distinct characters across all names
long uniqueChars = students.stream()
.map(Student::name)
.flatMap(n -> n.chars().mapToObj(c -> (char) c).map(String::valueOf))
.distinct().count();
System.out.println("Unique chars in all names: " + uniqueChars);
}
}
// javac --enable-preview --release 21 StreamsDemo.java
// java --enable-preview StreamsDemo