Java Stream Intermediate Operations Examples

Introduction

Java 8 Streams support intermediate operations that return another stream, allowing developers to chain multiple operations together to form a pipeline. Intermediate operations are lazy, meaning they are not executed until a terminal operation is invoked. Some commonly used intermediate operations include filter(), map(), flatMap(), distinct(), sorted(), peek(), limit(), and skip().

In this tutorial, we will explore examples of each of these intermediate operations.

Table of Contents

  1. filter()
  2. map()
  3. flatMap()
  4. distinct()
  5. sorted()
  6. peek()
  7. limit()
  8. skip()

1. filter()

The filter() method is used to retain elements in the stream that match a given predicate (condition). Non-matching elements are excluded.

Code Example

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class FilterExample {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

        // Filter even numbers
        List<Integer> evenNumbers = numbers.stream()
                                           .filter(n -> n % 2 == 0)
                                           .collect(Collectors.toList());

        System.out.println(evenNumbers);
    }
}

Output

[2, 4, 6, 8, 10]

Explanation

  • The filter() operation retains only the even numbers in the list.

2. map()

The map() method is used to transform each element in the stream by applying a function. It creates a new stream with the modified elements.

Code Example

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class MapExample {
    public static void main(String[] args) {
        List<String> words = Arrays.asList("java", "stream", "api");

        // Convert each word to uppercase
        List<String> upperCaseWords = words.stream()
                                           .map(String::toUpperCase)
                                           .collect(Collectors.toList());

        System.out.println(upperCaseWords);
    }
}

Output

[JAVA, STREAM, API]

Explanation

  • The map() operation transforms each string to uppercase.

3. flatMap()

The flatMap() method is used to flatten nested collections or arrays into a single stream. It applies a function to each element and then flattens the result.

Code Example

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class FlatMapExample {
    public static void main(String[] args) {
        List<List<String>> nestedList = Arrays.asList(
                Arrays.asList("Java", "Python"),
                Arrays.asList("C++", "Go")
        );

        // Flatten the nested list
        List<String> flatList = nestedList.stream()
                                          .flatMap(List::stream)
                                          .collect(Collectors.toList());

        System.out.println(flatList);
    }
}

Output

[Java, Python, C++, Go]

Explanation

  • The flatMap() operation flattens the nested lists into a single list.

4. distinct()

The distinct() method removes duplicate elements from the stream, ensuring only unique elements are passed to the next operation.

Code Example

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class DistinctExample {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 2, 3, 4, 4, 5);

        // Remove duplicates
        List<Integer> uniqueNumbers = numbers.stream()
                                             .distinct()
                                             .collect(Collectors.toList());

        System.out.println(uniqueNumbers);
    }
}

Output

[1, 2, 3, 4, 5]

Explanation

  • The distinct() operation filters out duplicate elements from the list.

5. sorted()

The sorted() method sorts the elements of the stream in natural order or using a custom comparator.

Code Example

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class SortedExample {
    public static void main(String[] args) {
        List<String> names = Arrays.asList("Rahul", "Amit", "Deepa", "Suresh");

        // Sort names in alphabetical order
        List<String> sortedNames = names.stream()
                                        .sorted()
                                        .collect(Collectors.toList());

        System.out.println(sortedNames);
    }
}

Output

[Amit, Deepa, Rahul, Suresh]

Explanation

  • The sorted() operation arranges the names in natural (alphabetical) order.

6. peek()

The peek() method is mainly used for debugging purposes. It allows us to see the elements in the stream as they are processed, without modifying them.

Code Example

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class PeekExample {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

        // Peek to see the elements before filtering
        List<Integer> filteredNumbers = numbers.stream()
                                               .peek(n -> System.out.println("Before filtering: " + n))
                                               .filter(n -> n % 2 == 0)
                                               .collect(Collectors.toList());

        System.out.println("Filtered numbers: " + filteredNumbers);
    }
}

Output

Before filtering: 1
Before filtering: 2
Before filtering: 3
Before filtering: 4
Before filtering: 5
Filtered numbers: [2, 4]

Explanation

  • The peek() operation allows us to inspect elements before applying the filter() operation.

7. limit()

The limit() method returns a stream consisting of the first n elements of the original stream.

Code Example

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class LimitExample {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

        // Limit the stream to the first 3 elements
        List<Integer> limitedNumbers = numbers.stream()
                                              .limit(3)
                                              .collect(Collectors.toList());

        System.out.println(limitedNumbers);
    }
}

Output

[1, 2, 3]

Explanation

  • The limit() operation restricts the stream to only the first 3 elements.

8. skip()

The skip() method skips the first n elements of the stream and returns a stream consisting of the remaining elements.

Code Example

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class SkipExample {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

        // Skip the first 5 elements
        List<Integer> skippedNumbers = numbers.stream()
                                              .skip(5)
                                              .collect(Collectors.toList());

        System.out.println(skippedNumbers);
    }
}

Output

[6, 7, 8, 9, 10]

Explanation

  • The skip() operation discards the first 5 elements, returning a stream of the remaining elements.

Conclusion

Java 8 Stream intermediate operations provide a functional way to process and manipulate collections. These operations allow developers to filter, transform, and manage data streams efficiently while creating concise and readable code. Understanding how to use each operation effectively enables developers to build complex data pipelines that perform well.

Comments