简体   繁体   中英

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.

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).

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());

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());

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM