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.

Selected Java Interview Questions
Selected Java Interview Questions
Selected Java Interview Questions
Java Stream API Overview and Practical Usage Examples

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<Student> studentStream = Arrays.stream(studentArr);
    // 3. Stream.of for var‑args
    Stream<Integer> stream1 = Stream.of(1,2,34,5,65);
    // 4. Stream.of for array streams (produces Stream<int[]>)
    Stream<int[]> stream2 = Stream.of(arr, arr);
    stream2.forEach(System.out::println);
}

From collections:

public static void main(String[] args) {
    List<String> strs = Arrays.asList("11212","dfd","2323","dfhgf");
    // ordinary stream
    Stream<String> stream = strs.stream();
    // parallel stream
    Stream<String> stream1 = strs.parallelStream();
}

2. Stream API Details

The BaseStream interface defines the fundamental operations for all streams.

public interface BaseStream<T, S extends BaseStream<T, S>> extends AutoCloseable {
    Iterator<T> iterator();
    Spliterator<T> 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<T> extends BaseStream<T, Stream<T>> {
    Stream<T> filter(Predicate<? super T> predicate);
    <R> Stream<R> map(Function<? super T, ? extends R> mapper);
    IntStream mapToInt(ToIntFunction<? super T> mapper);
    LongStream mapToLong(ToLongFunction<? super T> mapper);
    DoubleStream mapToDouble(ToDoubleFunction<? super T> mapper);
    <R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);
    Stream<T> distinct();
    Stream<T> sorted();
    Stream<T> sorted(Comparator<? super T> comparator);
    Stream<T> peek(Consumer<? super T> action);
    Stream<T> limit(long maxSize);
    Stream<T> skip(long n);
    void forEach(Consumer<? super T> action);
    void forEachOrdered(Consumer<? super T> action);
    Object[] toArray();
    <A> A[] toArray(IntFunction<A[]> generator);
    T reduce(T identity, BinaryOperator<T> accumulator);
    Optional<T> reduce(BinaryOperator<T> accumulator);
    <U> U reduce(U identity, BiFunction<U, ? super T, U> accumulator, BinaryOperator<U> combiner);
    <R> R collect(Supplier<R> supplier, BiConsumer<R, ? super T> accumulator, BiConsumer<R, R> combiner);
    <R, A> R collect(Collector<? super T, A, R> collector);
    Optional<T> min(Comparator<? super T> comparator);
    Optional<T> max(Comparator<? super T> comparator);
    long count();
    boolean anyMatch(Predicate<? super T> predicate);
    boolean allMatch(Predicate<? super T> predicate);
    boolean noneMatch(Predicate<? super T> predicate);
    Optional<T> findFirst();
    Optional<T> findAny();
    static <T> Builder<T> builder() { return new Streams.StreamBuilderImpl<>(); }
    static <T> Stream<T> empty() { return StreamSupport.stream(Spliterators.emptySpliterator(), false); }
    static <T> Stream<T> of(T t) { return StreamSupport.stream(new Streams.StreamBuilderImpl<>(t), false); }
    @SafeVarargs static <T> Stream<T> of(T... values) { return Arrays.stream(values); }
    static <T> Stream<T> iterate(final T seed, final UnaryOperator<T> f) { /* implementation omitted */ }
    static <T> Stream<T> generate(Supplier<T> s) { /* implementation omitted */ }
    static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b) { /* implementation omitted */ }
}

2.1 Common Operations

Filtering and Matching

List<Integer> intList = Arrays.asList(6,7,3,8,1,2,9);
List<Integer> collect = intList.stream().filter(x -> x > 7).collect(Collectors.toList());
System.out.println(collect); // [8,9]

List<Person> collect2 = personList.stream().filter(p -> p.getSalary() > 8000).collect(Collectors.toList());

Optional<Integer> findFirst = list.stream().filter(x -> x > 6).findFirst();
Optional<Integer> findAny = list.parallelStream().filter(x -> x > 6).findAny();
boolean anyMatch = list.stream().anyMatch(x -> x < 6);

Aggregation (max, min, count)

Optional<String> max = list.stream().max(Comparator.comparing(String::length));
Optional<Integer> maxInt = list.stream().max(Comparator.naturalOrder());
Optional<Person> 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<Integer> 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<String> nameList = personList.stream().map(Person::getName).collect(Collectors.toList());
Set<String> nameSet = personList.stream().map(Person::getName).collect(Collectors.toSet());
Map<String, Person> personMap = personList.stream().collect(Collectors.toMap(Person::getName, p -> p));
Map<String, List<Person>> groupByName = personList.stream().collect(Collectors.groupingBy(Person::getName));
Map<String, Map<Integer, List<Person>>> 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<Person> 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<String> s1 = Stream.of(arr1);
Stream<String> 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.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaAPICollectionsStreamFunctionalProgramming
Selected Java Interview Questions
Written by

Selected Java Interview Questions

A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.