简体   繁体   English

如何使用 Java 流 api 过滤地图?

[英]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 .我想取回字符串列表,即匹配键值的地图中的值,在“选择”列表中找到。所以,我希望返回 {"f", "a"} 作为结果 Is there a way to use java stream api to do it in elegant way?有没有办法使用java流api以优雅的方式做到这一点?

When there is one value , I am doing it this way:当有一个 value 时,我这样做:

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).但是它可能效率不高,因为List::contains是 O(N)。 Consider using a Set (for example HashSet ) instead of List for picks as HashSet::contains is O(1).考虑使用Set (例如HashSet )而不是List进行picks因为HashSet::contains是 O(1)。

You can use List.contains() in the Stream#filter to only accept those values which are present in the list:您可以在Stream#filter使用List.contains()来仅接受列表中存在的那些值:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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