Skip to main content
Advertisement

Intermediate Operations

Intermediate operations build the stream pipeline by specifying what transformation or filtering logic should be applied. They always return a new Stream, allowing multiple intermediate operations to be chained together continuously.

1. Filtering: filter, distinct

Used when extracting elements that match a specific condition or removing duplicates.

  • filter(Predicate): Selects elements that satisfy the given condition (a lambda expression returning true).
  • distinct(): Removes duplicate elements from the stream (using Object.equals() internally).
List<Integer> numbers = Arrays.asList(1, 2, 2, 3, 4, 4, 5);

numbers.stream()
.distinct() // Removes duplicates: 1, 2, 3, 4, 5
.filter(n -> n % 2 == 0) // Extracts even numbers: 2, 4
.forEach(System.out::println);

2. Transformation: map, flatMap

Extremely common operations used to transform the shape or type of data.

  • map(Function): Replaces each element in the stream with a different value, or extracts specific fields from an object.
  • flatMap(Function): Flattens nested structures (e.g., a list of string arrays) into a single, unified stream.
List<String> words = Arrays.asList("apple", "banana", "cherry");

// Convert all words to uppercase
words.stream()
.map(String::toUpperCase)
.forEach(System.out::println); // APPLE, BANANA, CHERRY
// flatMap example
List<List<String>> nestedList = Arrays.asList(
Arrays.asList("A", "B"),
Arrays.asList("C", "D")
);

// Flatten into a single layer structure
nestedList.stream()
.flatMap(Collection::stream)
.forEach(System.out::print); // Prints ABCD

3. Sorting: sorted

Sorts the elements. If no arguments are passed, it uses the natural ordering (Comparable). Alternatively, a custom Comparator can be provided.

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

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

// Reverse Alphabetical Sort
names.stream()
.sorted(Comparator.reverseOrder())
.forEach(System.out::println); // Charlie, Bob, Alice

4. Truncating: limit, skip

  • limit(long maxSize): Truncates the stream to contain no more than the specified number of elements.
  • skip(long n): Discards the first n elements of the stream.
IntStream.rangeClosed(1, 10)  // 1 through 10
.skip(3) // Skips 1, 2, 3 (Starts from 4)
.limit(2) // Only takes 2 elements
.forEach(System.out::println); // Prints 4, 5

By assembling these versatile intermediate operations like Lego blocks, developers can construct powerful and readable data processing pipelines.

Advertisement