Java Stream API Overview and Practical Usage Examples
This article provides a comprehensive guide to Java 8 Stream API, covering its core characteristics, creation methods, essential interfaces, and common operations such as filtering, mapping, reducing, collecting, grouping, and sorting, with clear code examples for each concept.
1. Basic Characteristics
Java 8 introduced the Stream API, which treats collections or arrays as a flow of elements that can be filtered, sorted, and processed without storing intermediate results.
1.1 Stream Features
stream does not store data; it computes results on demand.
stream does not modify the source; it typically produces a new collection.
stream operations are lazy and execute only when a terminal operation is invoked.
Streams are single‑use; invoking a terminal operation on a consumed stream throws an exception.
1.2 Creating Streams
From arrays:
public static void main(String[] args) {
// 1. Arrays.stream for primitive types
int[] arr = new int[]{1,2,34,5};
IntStream intStream = Arrays.stream(arr);
// 2. Arrays.stream for reference types
Student[] studentArr = new Student[]{new Student("s1",29), new Student("s2",27)};
Stream
studentStream = Arrays.stream(studentArr);
// 3. Stream.of for var‑args
Stream
stream1 = Stream.of(1,2,34,5,65);
// 4. Stream.of for array streams (produces Stream
)
Stream
stream2 = Stream.of(arr, arr);
stream2.forEach(System.out::println);
}From collections:
public static void main(String[] args) {
List
strs = Arrays.asList("11212","dfd","2323","dfhgf");
// ordinary stream
Stream
stream = strs.stream();
// parallel stream
Stream
stream1 = strs.parallelStream();
}2. Stream API Details
The BaseStream interface defines the fundamental operations for all streams.
public interface BaseStream
> extends AutoCloseable {
Iterator
iterator();
Spliterator
spliterator();
boolean isParallel();
S sequential();
S parallel();
S unordered();
S onClose(Runnable closeHandler);
@Override void close();
}The Stream interface extends BaseStream and adds a rich set of intermediate and terminal operations.
public interface Stream
extends BaseStream
> {
Stream
filter(Predicate
predicate);
Stream
map(Function
mapper);
IntStream mapToInt(ToIntFunction
mapper);
LongStream mapToLong(ToLongFunction
mapper);
DoubleStream mapToDouble(ToDoubleFunction
mapper);
Stream
flatMap(Function
> mapper);
Stream
distinct();
Stream
sorted();
Stream
sorted(Comparator
comparator);
Stream
peek(Consumer
action);
Stream
limit(long maxSize);
Stream
skip(long n);
void forEach(Consumer
action);
void forEachOrdered(Consumer
action);
Object[] toArray();
A[] toArray(IntFunction
generator);
T reduce(T identity, BinaryOperator
accumulator);
Optional
reduce(BinaryOperator
accumulator);
U reduce(U identity, BiFunction
accumulator, BinaryOperator
combiner);
R collect(Supplier
supplier, BiConsumer
accumulator, BiConsumer
combiner);
R collect(Collector
collector);
Optional
min(Comparator
comparator);
Optional
max(Comparator
comparator);
long count();
boolean anyMatch(Predicate
predicate);
boolean allMatch(Predicate
predicate);
boolean noneMatch(Predicate
predicate);
Optional
findFirst();
Optional
findAny();
static
Builder
builder() { return new Streams.StreamBuilderImpl<>(); }
static
Stream
empty() { return StreamSupport.stream(Spliterators.emptySpliterator(), false); }
static
Stream
of(T t) { return StreamSupport.stream(new Streams.StreamBuilderImpl<>(t), false); }
@SafeVarargs static
Stream
of(T... values) { return Arrays.stream(values); }
static
Stream
iterate(final T seed, final UnaryOperator
f) { /* implementation omitted */ }
static
Stream
generate(Supplier
s) { /* implementation omitted */ }
static
Stream
concat(Stream
a, Stream
b) { /* implementation omitted */ }
}2.1 Common Operations
Filtering and Matching
List
intList = Arrays.asList(6,7,3,8,1,2,9);
List
collect = intList.stream().filter(x -> x > 7).collect(Collectors.toList());
System.out.println(collect); // [8,9]
List
collect2 = personList.stream().filter(p -> p.getSalary() > 8000).collect(Collectors.toList());
Optional
findFirst = list.stream().filter(x -> x > 6).findFirst();
Optional
findAny = list.parallelStream().filter(x -> x > 6).findAny();
boolean anyMatch = list.stream().anyMatch(x -> x < 6);Aggregation (max, min, count)
Optional
max = list.stream().max(Comparator.comparing(String::length));
Optional
maxInt = list.stream().max(Comparator.naturalOrder());
Optional
maxPerson = list.stream().max(Comparator.comparingInt(Person::getSalary));
long count = list.stream().filter(x -> x > 6).count();Reduction (reduce)
Integer sum = list.stream().reduce(1, (x, y) -> x + y);
Optional
maxOpt = list.stream().reduce(Integer::max);
Integer sumSalary = personList.stream().reduce(0, (sum, p) -> sum + p.getSalary(), Integer::sum);Collecting (collect)
Double avgSalary = personList.stream().collect(Collectors.averagingDouble(Person::getSalary));
DoubleSummaryStatistics stats = personList.stream().collect(Collectors.summarizingDouble(Person::getSalary));
String names = personList.stream().map(Person::getName).collect(Collectors.joining(","));
List
nameList = personList.stream().map(Person::getName).collect(Collectors.toList());
Set
nameSet = personList.stream().map(Person::getName).collect(Collectors.toSet());
Map
personMap = personList.stream().collect(Collectors.toMap(Person::getName, p -> p));
Map
> groupByName = personList.stream().collect(Collectors.groupingBy(Person::getName));
Map
>> multiGroup = personList.stream().collect(Collectors.groupingBy(Person::getName, Collectors.groupingBy(Person::getSalary)));Mapping (map)
String[] arr = {"abcd","bcdd","defde","ftr"};
Arrays.stream(arr).map(String::toUpperCase).forEach(System.out::println);
personList.stream().map(Person::getSalary).forEach(System.out::println);
List
increased = personList.stream().map(p -> { p.setSalary(p.getSalary()+10000); return p; }).collect(Collectors.toList());Sorting (sorted)
String[] strs = {"abc","m","M","bcd"};
System.out.println(Arrays.stream(strs).sorted().collect(Collectors.toList())); // [M, abc, bcd, m]
Arrays.stream(strs).sorted(Comparator.comparing(String::length)).forEach(System.out::println);Stream Extraction and Combination
Stream
s1 = Stream.of(arr1);
Stream
s2 = Stream.of(arr2);
Stream.concat(s1, s2).distinct().forEach(System.out::println);
Stream.iterate(1, x -> x + 2).limit(10).forEach(System.out::println);
Stream.iterate(1, x -> x + 2).skip(1).limit(5).forEach(System.out::println);The article concludes with a list of additional interview‑question resources and a call‑to‑action for readers to follow the associated public account for more Java interview material.
Selected Java Interview Questions
A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.