Java 8 Stream forEach()

The forEach()method is used to iterate over elements in a collection or stream and perform a specified action on each element. In this post, we are going to explore Java 8 Stream forEach().

Syntax for Stream forEach() method:-

The forEach() method in Java streams has the following syntax:

void forEach(Consumer<? super T> action)

Components in this syntax:

  • forEach: This is the name of the method.
  • Consumer<? super T> action: The action parameter is a Consumer functional interface. It specifies the action to be performed on each element of the stream. The Consumer interface takes one argument (the element) and returns no result (void).

Here’s an example of how we can use the forEach() method.

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

names.stream()
     .forEach(name -> System.out.println("Hello, " + name));

In this example, forEach() is used to apply the specified action, which is a lambda expression (name -> System.out.println("Hello, " + name)), to each element in the stream of names.

Let’s see examples of using forEach() in both without using Java 8 and with Java 8.

Without Java 8:

Before Java 8, you would typically use an enhanced for loop (for-each loop) or a traditional for loop to iterate over a collection and perform an action on each element.

import java.util.ArrayList;
import java.util.List;

public class WithoutJava8Example {
    public static void main(String[] args) {
        List<String> names = new ArrayList<>();
        names.add("Alice");
        names.add("Bob");
        names.add("Charlie");

        // Using a for-each loop
        for (String name : names) {
            System.out.println(name);
        }
    }
}

With Java 8:

In Java 8 and later, you can use the forEach() method available on collections and streams to perform the same operation in a more concise and functional way.

import java.util.ArrayList;
import java.util.List;

public class Java8Example {
    public static void main(String[] args) {
        List<String> names = new ArrayList<>();
        names.add("Alice");
        names.add("Bob");
        names.add("Charlie");

        // Using forEach() with a lambda expression
        names.forEach(name -> System.out.println(name));

        // Alternatively, you can use a method reference
        names.forEach(System.out::println);
    }
}

In the Java 8 example, we use the forEach() method along with a lambda expression or method reference to iterate over the names list and print each element. This provides a more concise and expressive way to perform actions on elements in a collection or stream compared to traditional looping constructs.

Real-time use cases for Stream forEach() method

Here are five different real-time use cases for the forEach() method in Java streams.

1. Logging Elements.:

Use Case: Log each element in a list of log messages.

List<String> logMessages = Arrays.asList("Log message 1", "Log message 2", "Log message 3");

logMessages.stream()
           .forEach(System.out::println);

In this example, we use forEach() to print each log message to the console. This is a common use case for logging elements in a collection.

Output:

Log message 1
Log message 2
Log message 3

2. Updating Database Records:

Use Case: Update records in a database for each element in a list.

List<Integer> employeeIds = Arrays.asList(101, 102, 103);

employeeIds.stream()
           .forEach(id -> updateDatabase(id));

Here, we use forEach() to update database records for a list of employee IDs. The updateDatabase() method is called for each ID, which might perform a database update operation.

3. Sending Emails:

Use Case: Send emails to a list of recipients.

List<String> emailAddresses = Arrays.asList("user1@example.com", "user2@example.com", "user3@example.com");

emailAddresses.stream()
             .forEach(email -> sendEmail(email));

In this scenario, we use forEach() to send emails to a list of recipients. The sendEmail() method is called for each email address, which might send the email.

4. Processing Files:

Use Case: Process files in a directory.

List<File> fileList = Files.list(Paths.get("/path/to/directory"))
                         .collect(Collectors.toList());

fileList.stream()
        .forEach(file -> processFile(file));

This example demonstrates how to process files in a directory using forEach(). The processFile() method is called for each file found in the directory.

5. User Notifications:

Use Case: Notify users of an event.

Set<User> usersToNotify = getUserSetForEvent(event);

usersToNotify.stream()
            .forEach(user -> sendNotification(user, event));

Explanation: Here, we use forEach() to send event notifications to a set of users. The sendNotification() method is called for each user in the set, which might send a notification specific to that user and event.

These examples showcase how the forEach() method can be applied in various real-time scenarios to perform actions on each element of a stream or collection.

The forEach() method in Java streams is a powerful tool for performing operations on elements within a stream. Here are four important points to know about it:

  1. Iteration over Stream Elements: forEach() allows us to iterate over each element in a stream and perform a specific action for each element. This action is specified as a lambda expression or method reference, making it concise and expressive.
  2. Order of Execution: When using forEach() on a sequential stream, the elements are processed in the order they appear in the stream. However, when using it on a parallel stream, there is no guarantee of order, as multiple elements may be processed concurrently.
  3. Terminal Operation: forEach() is a terminal operation in Java streams. It consumes the elements of the stream and doesn’t return a new stream. Once forEach() is applied, the stream is considered consumed and cannot be used for further stream operations.
  4. Use Cases: forEach() is commonly used for actions like printing elements, updating external data structures, or performing side effects. It’s a functional way to process elements in a stream without explicit loops and is particularly useful for readability and code conciseness.

Example using forEach() to print elements in a list:

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

names.stream()
     .forEach(name -> System.out.println("Hello, " + name));

In this example, the forEach() method is used to print a greeting for each name in the names list.

Ten objective questions related to the Java 8 Stream forEach() method. The answers are provided at the end.

1. What is the primary purpose of the forEach() method in Java 8 streams?

A. To filter elements in a stream.

B. To map elements to a new stream.

C. To iterate over elements in a stream and perform an action on each element.

D. To create a new stream based on a given predicate.

2. Which functional interface is used as the parameter for the forEach() method?

A. Supplier

B. Predicate

C. Consumer

D. Function

3. In a parallel stream, which of the following statements is true about the order of execution in forEach()?

A. Elements are processed in reverse order.

B. The order of execution is random, not guaranteed.

C. Elements are processed in the same order as they appear in the stream.

D. Elements are processed in a sorted order.

4. What happens to a stream after the forEach() method is applied to it?

A. The stream is closed and cannot be used again.

B. The stream is converted into an array.

C. The stream remains open for further operations.

D. The stream is converted into a list.

5. Which of the following is a common real-time use case for the forEach() method?

A. Sorting elements in a collection.

B. Calculating the average of elements in a stream.

C. Logging elements in a collection.

D. Combining elements in a stream.

6. In a stream of integers, what would be the output of the following forEach() operation?

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
numbers.stream()
       .forEach(System.out::print);

A. 12345

B. 54321

C. 15

D. 543210

7. Which of the following is a valid way to use the forEach() method with a stream?

A. stream.forEach(action)

B. stream.apply(action)

C. stream.collect(action)

D. stream.transform(action)

8. What is the return type of the forEach() method?

A. Stream

B. Collection

C. List

D. void

9. When using the forEach() method with a stream of objects, which Java feature is often used to specify the action to be performed?

A. Lambda expressions

B. Annotations

C. Inheritance

D. Interfaces

10. What is the time complexity of the forEach() operation on a sequential stream with N elements?

A. O(1)

B. O(log N)

C. O(N)

D. O(N^2)

Answers:

  1. C. To iterate over elements in a stream and perform an action on each element.
  2. C. Consumer
  3. B. The order of execution is random, not guaranteed.
  4. A. The stream is closed and cannot be used again.
  5. C. Logging elements in a collection.
  6. A. 12345
  7. A. stream.forEach(action)
  8. D. void
  9. A. Lambda expressions
  10. C. O(N)

That’s all about Java 8 Stream forEach().

Other Java 8 examples.