有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

lambda如何使用Java流api过滤映射?

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

现在我有一个清单:

List<Integer> picks = {1,3}

我想从映射中获取字符串列表,即与“pick”列表中的键值相匹配的值。所以,我希望得到{“f”,“a”}作为结果。有没有一种方法可以使用java流api以优雅的方式完成它

当有一个值时,我是这样做的:

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

但是,当有一系列的关键点/选择要过滤时,就很难做到这一点


共 (3) 个答案

  1. # 1 楼答案

    您不需要遍历整个地图来收集拾取的值。而是迭代所需的键并从映射中获取相关值。如果与通常情况下需要选择的值相比,映射要大得多,那么这种方法应该优于另一种方法。此外,这个解决方案更紧凑,对我来说视觉混乱更少。这是它的样子

    List<String> pickedValues = picks.stream().map(map::get)
        .filter(Objects::nonNull)
        .collect(Collectors.toList());
    
  2. # 2 楼答案

    您可以通过以下方式实现这一点:

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

    输出:

    f
    a
    

    然而,它可能不是有效的,因为List::contains是O(N)。考虑使用^{}(例如^{})而不是^ {< CD4> }作为{{CD5}},因为^ {< CD6> }是O(1)。

  3. # 3 楼答案

    您可以在Stream#filter中使用List.contains()仅接受列表中存在的值:

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