DEV Community

Nikko Ferwelo
Nikko Ferwelo

Posted on

🚀 Understanding the Difference Between `filter` and `map` in Java Stream API

Hey there, fellow developers! 👋

If you’ve been diving into Java’s Stream API, you’ve likely come across two essential operations: filter and map. While both are powerful tools for manipulating streams of data, they serve different purposes and are often used together in stream processing pipelines. In this blog post, we’ll break down the differences between filter and map, and explore how you can use them effectively in your Java projects.

Let’s get started! 🚀

🔗 What is filter in Java Stream API?

The filter method is used to screen out elements from a stream based on a given condition. It returns a new stream that contains only the elements that match the condition (or predicate) specified.

Use Case: You use filter when you want to include only those elements in your stream that satisfy a certain condition.

Syntax:

Stream<T> filter(Predicate<? super T> predicate)
Enter fullscreen mode Exit fullscreen mode

Example:

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

List<String> filteredNames = names.stream()
                                  .filter(name -> name.startsWith("A"))
                                  .collect(Collectors.toList());

System.out.println(filteredNames); // Output: [Alice]
Enter fullscreen mode Exit fullscreen mode

Explanation: In this example, filter is used to create a new stream that includes only the names starting with "A".

🔗 What is map in Java Stream API?

The map method is used to transform each element of a stream into another form. It applies a given function to each element and returns a new stream containing the transformed elements.

Use Case: You use map when you want to convert or transform the elements of a stream into another type or format.

Syntax:

<R> Stream<R> map(Function<? super T, ? extends R> mapper)
Enter fullscreen mode Exit fullscreen mode

Example:

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

List<Integer> nameLengths = names.stream()
                                 .map(String::length)
                                 .collect(Collectors.toList());

System.out.println(nameLengths); // Output: [5, 3, 7, 5]
Enter fullscreen mode Exit fullscreen mode

Explanation: In this example, map is used to transform each name into its corresponding length, resulting in a stream of integers.

🚧 Key Differences Between filter and map

  • Purpose:

    • filter: Used to select elements based on a condition (i.e., it filters the elements).
    • map: Used to transform or convert elements from one form to another (i.e., it maps the elements).
  • Input/Output:

    • filter: Takes a Predicate as an argument and produces a stream with the same type of elements but with fewer elements.
    • map: Takes a Function as an argument and produces a stream with a potentially different type of elements.
  • Result:

    • filter: Produces a stream with elements that meet the filtering condition.
    • map: Produces a stream with elements that are the result of applying a transformation function.

🧩 Combining filter and map

Often, filter and map are used together in a stream pipeline to first narrow down the elements and then transform them.

Example:

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

List<Integer> filteredNameLengths = names.stream()
                                         .filter(name -> name.length() > 3)
                                         .map(String::length)
                                         .collect(Collectors.toList());

System.out.println(filteredNameLengths); // Output: [5, 7, 5]
Enter fullscreen mode Exit fullscreen mode

Explanation: Here, we first filter the names to include only those with more than three characters, and then we map each name to its length.

🚀 Practical Applications

  1. Filtering and Mapping User Data:
   List<User> users = getUsers();

   List<String> usernames = users.stream()
                                 .filter(user -> user.getAge() > 18)
                                 .map(User::getUsername)
                                 .collect(Collectors.toList());
Enter fullscreen mode Exit fullscreen mode

Explanation: Filter out users under 18, and then map the remaining users to their usernames.

  1. Processing Transaction Data:
   List<Transaction> transactions = getTransactions();

   double totalAmount = transactions.stream()
                                    .filter(Transaction::isProcessed)
                                    .mapToDouble(Transaction::getAmount)
                                    .sum();
Enter fullscreen mode Exit fullscreen mode

Explanation: Filter transactions that have been processed, and then map to their amounts and sum them up.

🧠 Conclusion

Understanding the difference between filter and map in Java Stream API is crucial for writing clean and efficient stream processing code. Use filter to narrow down your data, and use map to transform it. Combining these operations can lead to powerful data manipulation pipelines that are both readable and maintainable.

I hope this blog helps clarify the roles of filter and map in your Java development journey! Feel free to bookmark it for quick reference or share it with your fellow developers.

Got any questions or additional tips? Drop them in the comments below! Happy coding! 💻

Connect with me:


Top comments (0)