Java Streams API

The Java Streams API (introduced in Java 8) provides a modern, functional-style way to process collections of data. It allows you to work with sequences of elements (like List, Set, or arrays) using declarative operations such as filtering, mapping, reducing, collecting, and more, while supporting parallel execution.


Key Concepts

  • Stream: A sequence of elements supporting sequential and parallel operations.
  • Intermediate operations: Transform a stream into another stream (lazy operations). Examples: filter(), map(), sorted().
  • Terminal operations: Produce a result or a side-effect and end the stream pipeline. Examples: collect(), forEach(), reduce().

Examples

1. Creating Streams

import java.util.*;
import java.util.stream.*;

public class StreamExamples {
    public static void main(String[] args) {
        // From a list
        List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David");

        Stream<String> stream1 = names.stream();
        
        // From an array
        String[] arr = {"one", "two", "three"};
        Stream<String> stream2 = Arrays.stream(arr);

        // Using Stream.of
        Stream<Integer> stream3 = Stream.of(1, 2, 3, 4, 5);

        // Infinite stream (example: odd numbers)
        Stream<Integer> oddNumbers = Stream.iterate(1, n -> n + 2);
    }
}

2. Filtering

List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David");

names.stream()
     .filter(name -> name.startsWith("A"))
     .forEach(System.out::println);
// Output: Alice

3. Mapping

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");

names.stream()
     .map(String::toUpperCase)
     .forEach(System.out::println);
// Output: ALICE, BOB, CHARLIE

4. Sorting

List<String> names = Arrays.asList("Charlie", "Alice", "Bob");

names.stream()
     .sorted()
     .forEach(System.out::println);
// Output: Alice, Bob, Charlie

5. Collecting Results

List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David");

List<String> filtered = names.stream()
                             .filter(n -> n.length() > 3)
                             .collect(Collectors.toList());

System.out.println(filtered);
// Output: [Alice, Charlie, David]

6. Reduce (Aggregation)

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

int sum = numbers.stream()
                 .reduce(0, (a, b) -> a + b);

System.out.println(sum); 
// Output: 15

7. Parallel Streams

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

int sum = numbers.parallelStream()
                 .mapToInt(Integer::intValue)
                 .sum();

System.out.println(sum); 
// Output: 15

8. Grouping

List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David", "Anna");

Map<Character, List<String>> grouped =
    names.stream()
         .collect(Collectors.groupingBy(name -> name.charAt(0)));

System.out.println(grouped);
// Output: {A=[Alice, Anna], B=[Bob], C=[Charlie], D=[David]}

✅ When to use Streams?

  • When you want concise, readable, functional-style data processing.
  • When parallelism could improve performance (e.g., large datasets).
  • When you don’t need to modify the original collection.

Leave a Reply