articles

Home / DeveloperSection / Articles / Java Streams API: Intermediate and Terminal Operations

Java Streams API: Intermediate and Terminal Operations

Java Streams API: Intermediate and Terminal Operations

Ravi Vishwakarma 141 23-Jul-2024

The Java Streams API provides a modern way to process collections of objects. It allows for complex data processing tasks to be expressed in a concise and readable manner. Streams are sequences of elements that support various operations to transform or consume the data. 

These operations can be categorized into two types: intermediate and terminal operations.

 

Java Streams API: Intermediate and Terminal Operations

 

Intermediate Operations

Intermediate operations return a new stream. They are used to transform or filter the elements of the original stream but do not trigger any processing. They are lazy, meaning that they are not executed until a terminal operation is invoked on the stream. Intermediate operations are always stateless or stateful.

Common Intermediate Operations

filter: Selects elements based on a predicate.

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
List<String> filteredNames = names.stream()
                                  .filter(name -> name.startsWith("A"))
                                  .collect(Collectors.toList());
// Output: ["Alice"]

map: Transforms each element using a function.

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
List<Integer> nameLengths = names.stream()
                                 .map(String::length)
                                 .collect(Collectors.toList());
// Output: [5, 3, 7]

flatMap: Transforms each element into a stream and flattens the resulting streams into a single stream.

List<List<String>> listOfLists = Arrays.asList(Arrays.asList("Alice", "Bob"), Arrays.asList("Charlie"));
List<String> flatList = listOfLists.stream()
                                   .flatMap(List::stream)
                                   .collect(Collectors.toList());
// Output: ["Alice", "Bob", "Charlie"]

distinct: Removes duplicate elements.

List<Integer> numbers = Arrays.asList(1, 2, 2, 3, 4, 4);
List<Integer> distinctNumbers = numbers.stream()
                                       .distinct()
                                       .collect(Collectors.toList());
// Output: [1, 2, 3, 4]

sorted: Sorts the elements.

List<String> names = Arrays.asList("Charlie", "Alice", "Bob");
List<String> sortedNames = names.stream()
                                .sorted()
                                .collect(Collectors.toList());
// Output: ["Alice", "Bob", "Charlie"]

peek: Acts as each element of the stream.

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
List<String> peekedNames = names.stream()
                                .peek(name -> System.out.println(name))
                                .collect(Collectors.toList());
// Output: Prints each name to the console and returns the original list

Terminal Operations

Terminal operations produce a result or a side-effect and trigger the processing of the stream. Once a terminal operation is invoked, the stream can no longer be used.

Common Terminal Operations

collect: Converts the stream to a collection or another data structure.

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
List<String> collectedNames = names.stream()
                                   .collect(Collectors.toList());
// Output: ["Alice", "Bob", "Charlie"]

forEach: Acts as each element.

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
names.stream().forEach(System.out::println);
// Output: Prints each name to the console

reduce: Aggregates elements to a single value using an associative accumulation function.

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = numbers.stream()
                 .reduce(0, Integer::sum);
// Output: 15

toArray: Converts the stream to an array.

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
String[] namesArray = names.stream()
                           .toArray(String[]::new);
// Output: ["Alice", "Bob", "Charlie"]

findFirst: Returns the first element of the stream.

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
Optional<String> firstName = names.stream()
                                  .findFirst();
// Output: Optional[Alice]

count: Returns the number of elements in the stream.

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
long count = names.stream()
                  .count();
// Output: 3

anyMatch, allMatch, noneMatch: Check if any, all, or none of the elements match a given predicate.

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
boolean anyMatch = names.stream()
                        .anyMatch(name -> name.startsWith("A"));
// Output: true

Example Usage

Here is an example combining both intermediate and terminal operations:

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

public class StreamExample {
    public static void main(String[] args) {
        List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David", "Edward");

        List<String> filteredSortedNames = names.stream()
                                                .filter(name -> name.length() > 3)
                                                .sorted()
                                                .collect(Collectors.toList());

        System.out.println(filteredSortedNames);
        // Output: ["Alice", "Charlie", "David", "Edward"]
    }
}

Read more

Explain the Collections in Java

Features of Java 9, 10, 11. What's New?

Java Memory Management: Understanding Stack and Heap

Explain the Stream API introduced in Java 8. How does it work?


Updated 23-Jul-2024
Hi, my self Ravi Vishwakarma. I have completed my studies at SPICBB Varanasi. now I completed MCA with 76% form Veer Bahadur Singh Purvanchal University Jaunpur. SWE @ MindStick | Software Engineer | Web Developer | .Net Developer | Web Developer | Backend Engineer | .NET Core Developer

Leave Comment

Comments

Liked By