Using Filter on Stream of Maps in Java

Different examples of Filtering elements of a Map in Java using Java Streams and Plain Java.

Overview

This tutorial covers various examples of Filtering Java Map based on a given condition. We’ll use plain Java technique as well as Java Streams API to filter map elements and create a new HashMap or return a list of filtered elements only.

Setup Java Map

Before we jump to different examples of filtering Java Maps, let’s create an instance of Java Map with a few entries into it.

Consider we have a simple Person object.

class Person {
  Long personId;
  String name;
    
  // Constructors, Getters, and Setters 
}Code language: Java (java)

We’ll create a Map of Person instances with the personId as key.

Map<Long, Person> persons = Map.of(
    11L, new Person(11L, "Jon"),
    12L, new Person(12L, "James"),
    13L, new Person(13L, "Khal"),
    14L, new Person(14L, "Mark"),
    15L, new Person(15L, "Aarya")
);Code language: Java (java)

Filter Map Elements using Java Streams

Java Streams API provides a filter() function, which is a Stream Intermediate operation. This function applies the given condition (aka Predicate) on the elements of the stream and creates a stream of matching elements.

Consider, we want to create a Map of Persons whose name starts with a character ‘J’. We can specify this condition inside the filter function.

Map<Long, Person> output = persons.entrySet().stream()
  .filter(entry -> entry.getValue().getName().startsWith("J"))
  .collect(Collectors.toMap(
    Map.Entry::getKey, 
    Map.Entry::getValue));Code language: Java (java)

Firstly, we created a stream of our Map#Entry instances and used filter() to select only the Entries where person name starts with ‘J’. Lastly, we used Collectors#toMap() to collect the filtered entry elements in the form of a new Map.

11=Person(personId=11, name=Jon)
12=Person(personId=12, name=James)

As expected, the output map contains only two person entries.

Create a Generic Map Filter Function

We can slightly modify the previous example and create a generic reusable utility function to filter any map based on the provided predicate. The signature of our function looks like this.

public static <K, V> Map<K, V> filterMap(
    Map<K, V> map,
    Predicate<V> predicate){
 ...Code language: Java (java)

As you can see, the function accepts a generic Map and a value based Predicate condition. As an output the function returns a Map of the same generic type.

Let’s add logic to apply the provided predicate on the given map and return a filtered map.

public static <K, V> Map<K, V> filterMap(
    Map<K, V> map,
    Predicate<V> predicate) {

  return map.entrySet().stream()
    .filter(entry -> predicate.test(entry.getValue()))
    .collect(Collectors.toMap(
      Map.Entry::getKey,
      Map.Entry::getValue));
}Code language: Java (java)

Now, our generic Map filter function is ready. In the filter() function we simply applied the given predicate on the Map#Entry elements. Lastly, we collected the stream to create a new HashMap.

Now, let’s use this function to filter our Map and print the output.

Map<Long, Person> output = filterMap(
    persons, 
    value -> value.getName().startsWith("J"));Code language: Java (java)

We called the filterMap() function and provided a predicate to filter all persons with name starting with ‘J’.

11=Person(personId=11, name=Jon)
12=Person(personId=12, name=James)

As a result, we got the map with expected entries.

Filter Map and return Filtered Values

Instead of creating a new Map of the filtered elements, we may want to return only the filtered values. Next example, applies a filter on a Map and returns a list of matching values.

List<Person> names = persons.values().stream()
  .filter(person -> person.getName().startsWith("j"))
  .collect(Collectors.toList());Code language: PHP (php)

As we are only interested in filtered values of the Map, we created a Stream of value elements. Then, we applied our filter and collected the filtered values in the form of a List.

Filter Map Elements using Plain Java

Let’s cover a simple example of filtering Map elements using Plain Java.

Map<Long, Person> output = new HashMap<>();
for (Map.Entry<Long, Person> entry : persons.entrySet()) {
  if (entry.getValue().getName().startsWith("J")) {
    output.put(entry.getKey(), entry.getValue());
  }
}Code language: Java (java)

Here, we manually iterated through the Map Entry instances and added selected entries into the output map.

Summary

This was an example oriented tutorial on Filtering Java Map elements. We have used Java Streams to specify a predicate to filter Map elements and collect the filtered elements in a new HashMap or collect the filtered values into a List. We have also created a Java Stream based generic filter function that can be reused to filter Map elements based on a predicate. Lastly, we covered a plain java way of Map filters.