【问题标题】:Using Streams filter Map based on a list of keys使用基于键列表的 Streams 过滤器映射
【发布时间】:2019-06-14 16:44:34
【问题描述】:

我有一个特殊问题,想知道 Java 8 Streams API 是否可以解决它。我知道这可以在使用 Streams API 之外完成,但如果可以使用 Streams 完成,我不想添加与尝试实现该目标相关的所有样板代码。我有地图

Map<String, String> greetings = new HashMap<>();
greetings.put("abc", "Hello");
greetings.put("def", "Goodbye");
greetings.put("ghi", "Ciao");
greetings.put("xyz", "Bonsoir");

还有一个键列表:

List<String> keys = Arrays.asList("def", "zxy");

将上述内容与 Streams API 一起使用,是否可以将其过滤为:

Map<String, String> filteredGreetings = new HashMap<>();
filteredGreetings.put("def", "Goodbye");
filteredGreetings.put("xyz", "Bonsoir");

希望这对我想要实现的目标有意义。

到目前为止,我只有在指定过滤地图的 keySet 的确切键时才能使用它,但是这只会返回一个条目集。我对完全过滤的地图感兴趣,我正在努力实现这一目标。

【问题讨论】:

  • 只是巧合、错别字还是要求,我注意到了键"zxy",结果仍然是put("xyz", "Bonsoir")
  • 是的,这是一个错字。道歉

标签: java collections java-8 java-stream


【解决方案1】:

如果问题is not a typo中的输入和预期输出,也可以保留输入映射的key为:

Map<String, String> futureGreetings = new HashMap<>(greetings);
futureGreetings.keySet().retainAll(keys);

【讨论】:

  • 当然,这不使用流,但可以在选择之前比较这两种解决方案的复杂性和可读性。
  • 这是最好最简单的解决方案。比我的好多了;)
【解决方案2】:

试试这个:

Map<String, String> result = keys.stream()
        .filter(greetings::containsKey)
        .collect(Collectors.toMap(Function.identity(), greetings::get));

或者反过来:

Map<String, String> result = greetings.entrySet().stream()
        .filter(e -> keys.contains(e.getKey()))
        .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

对于第二种方法,我建议将Set&lt;String&gt; 用于更大的keys 列表,因为它对于.contains() 具有O(1) 时间复杂度,因为它不包含任何重复:

Set<String> keys = new HashSet<>(Arrays.asList("def", "zxy"));

【讨论】:

  • 对于两个元素的列表,时间复杂度真的无关紧要。事实上,散列的开销会比线性查找高。
  • @Holger 是的,这是真的。只是想添加一般信息。
  • @SamuelPhilipp 现场 - 非常感谢!我也不知道“身份”。我需要阅读更多关于此的内容。
  • @RichardC Function.identity()i -&gt; i 的同义词。
【解决方案3】:

试试这个

filteredGreetings= keys.stream()
                  .collect(Collectors.toMap(Function.identity(),key->greetings.get(key)));

甚至对于缺少的密钥,您也可以使用getOrDefault() 方法。

... .collect(Collectors.toMap(Function.identity(),key->greetings.getOrDefault(key,"")));

【讨论】:

  • 因为我添加了第二种方法。虽然我认为他并不是说钥匙不存在
猜你喜欢
  • 1970-01-01
  • 2018-01-01
  • 2016-07-22
  • 2021-02-16
  • 2020-04-05
  • 2021-08-13
  • 2018-08-22
  • 2023-03-23
  • 2022-01-18
相关资源
最近更新 更多