So you've got a Map object in your Java application and you'd like to filter it to include only the entries that match specific criteria?

No problem. I can help you with that.

And in this guide, I will help you with that.

I'll show you how to do what you want with the aid of the Stream object.

Getting Started

Let's assume for the purposes of this guide that you're working on a CRM app. You've got a map that associates customers with their total purchases in U.S. dollars.

Get some test data going with this code:

Map<String, Integer> map = new LinkedCaseInsensitiveMap<>();
map.put("Janice", 100000);
map.put("Jerry", 20000);
map.put("Buck", 500000);

Now let's further assume that you're at the point where you're handling some requirement for the application and you need to just grab a subset of those entries instead of all of them.

You can't use a simple get() method because:

  • you may need to retrieve more than one object
  • the criteria for matching objects might not have anything to do with the key

So you gotta do something else.

That something else involves using the Stream class.

Gently Down the Stream

Suppose you want all the customers with sales greater than $50,000. Here's how you can make that happen:

Map<String, String> filteredMap = map
                                    .entrySet()
                                    .stream()
                                    .filter(e -> e.getValue() > 50000)
                                    .collect(
                                        Collectors.toMap(
                                          e -> String.valueOf(e.getKey()),
                                          e -> String.valueOf(e.getValue()),
                                          (oldValue, newValue) -> oldValue, HashMap::new
                                      ));
System.err.println(filteredMap);

Add that to the previous code block and the output will look like this:

{Buck=500000, Janice=100000}

And that's what it should look like because those are the only two entries with sales more than $50,000.

Now let me explain what's going on in the code.

Big picture: it creates a new Map object that only includes the entries from the original Map object that match the criteria.

First the code above gets the entry set from the Map object. That's nothing more than a Set of Entry objects.

An Entry in a Map object represents a key/value pair.

Next, the code instantiates a Stream object from the Set. You can see that with the stream() method.

Then the code handles the criteria. It uses the filter() method to find the entries that match.

As you can see, it's finding the entries with the value field set to a number that's more than 50,000. And that makes sense because the value in the entry is the customer's total sales amount in dollars and you want customers with sales that exceed $50,000.

That filter() method, by the way, returns a Stream object that only includes elements that match the filter.

Finally, the code creates a new Map using the collect() method.

The end result: you get a new Map object that only includes the customers with sales that exceed $50,000.

By the way: if you're interested in preserving insertion order, just change that HashMap::new in the code above to LinkedHashMap::new.

But you usually won't need to preserve insertion order with maps.

Wrapping It Up

So that's it. Now you know how to filter a Map object.

Take what you've learned here and start using it in your own code. Just update the filter() to suit your own requirements.

In some cases, you might need to add multiple filter() methods. But that's easy enough to do with method chaining.

Have fun!

Photo by Maria Orlova from Pexels