Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to filter a map with Java stream api?

Map<Integer, String> map = new HashMap<>();
  map.put(1, "f");
  map.put(2, "I");
  map.put(3, "a");
  map.put(4, "c");....etc

Now I have a list:

List<Integer> picks = {1,3}

I would like to get back a list of Strings, ie, values from map that matches the key values, found in the 'pick' list.So, I am expecting to get back {"f", "a"} as result. Is there a way to use java stream api to do it in elegant way?

When there is one value , I am doing it this way:

map.entrySet().stream()
   .filter(entry -> "a".equals(entry.getValue()))
   .map(entry -> entry.getValue())
   .collect(Collectors.toList())

But getting hard time when there is a list of keys/picks to filter with.

like image 773
VictorGram Avatar asked Aug 21 '19 18:08

VictorGram


People also ask

What is filter and map in Stream Java?

The map() will then return a Stream of Integer which contains both even and odd numbers. To select just even numbers, we can use the filter() method. It takes a predicate object which is technically a function to convert an object to a boolean. We pass an object and it will return true or false.

How do you filter maps?

Step 1 Go to Add/Manage Map -> Edit Page. Step 2 Assign those Locations using Choose Locations section, which you want to display on a google maps. Step 3 Scroll down to Custom Filters and insert placeholders like {country},{state},{city}. Insert Filter text according to it Filter placeholder.

Can we use filter and map together in Java 8?

Once we have the Stream of Integer, we can apply maths to find the even numbers. We passed that condition to filter method. If we needed to filter on String, e.g. select all string which has length > 2, then we would have called filter before map. That's all about how to use map and filter in Java 8.

Can we use Stream with map in Java?

Converting only the Value of the Map<Key, Value> into Stream: This can be done with the help of Map. values() method which returns a Set view of the values contained in this map. In Java 8, this returned set can be easily converted into a Stream of key-value pairs using Set. stream() method.


3 Answers

You can use List.contains() in the Stream#filter to only accept those values which are present in the list:

List<String> result = map.entrySet()
   .stream()
   .filter(ent -> picks.contains(ent.getKey()))
   .map(Map.Entry::getValue)     
   .collect(Collectors.toList());
like image 119
Fullstack Guy Avatar answered Oct 13 '22 16:10

Fullstack Guy


You can achieve this by using something like this :

List<String> values = map.entrySet()
                .stream()
                .filter(entry -> picks.contains(entry.getKey()))
                .map(Map.Entry::getValue)
                .collect(Collectors.toList());

values.forEach(System.out::println);

Output:

f
a

However it might not be efficient as List::contains is O(N). Consider using a Set (for example HashSet) instead of List for picks as HashSet::contains is O(1).

like image 35
Michał Krzywański Avatar answered Oct 13 '22 17:10

Michał Krzywański


You don't need to traverse the entire map just to collect picked values. Rather iterate over the required keys and grab the relevant values from the map. If the map is far more larger compared to the values you need to pick which is usually the case, then this approach should outperform the other. Moreover this solution is much more compact and has less visual clutter to me. Here's how it looks.

List<String> pickedValues = picks.stream().map(map::get)
    .filter(Objects::nonNull)
    .collect(Collectors.toList());
like image 32
Ravindra Ranwala Avatar answered Oct 13 '22 18:10

Ravindra Ranwala