【问题标题】:How to return a Set View of Keys with existing Values?如何返回具有现有值的键的集合视图?
【发布时间】:2021-05-17 09:14:54
【问题描述】:

例如,如果我有一个包含 10 个键的 HashMap,但只有 4 个键有值。如何返回这些键的 SetView。我只找到了 Map.keySet() 方法,但是这个方法给了我这个 Hashmap 中的每一个键。 我只需要那些价值 !=null !!! 对不起我的英语不好,我是德国人:)

【问题讨论】:

标签: java hashmap set key keyset


【解决方案1】:

使用keySet()方法,遍历Set中的每个Entry,每次检查Entry的值。如果此“值”为空,则我们将其从 Set 中删除。

Set<Map.Entry<String, String>> entrySet = new HashSet<>(yourMap.entrySet());
for(Map.Entry<String, String> entry : entrySet){
       if(entry.getValue() == null){
            entrySet.remove(entry);
       }
}

结果集“entrySet”就是你要找的东西

【讨论】:

  • 错误 1:entrySet() 返回地图的 视图,因此当您调用 remove() 时,您正在从地图本身中删除条目。 --- 错误2:在迭代时调用remove(entry)会导致ConcurrentModificationException
  • @Andreas,感谢您的错误。但是你的第二个错误是不对的,它不会抛出 ConcurrentModificationException。但是您的第一个错误是有效的,我编辑了代码,使其仅克隆条目集:)
  • HashSet的Javadoc:这个类的iterator方法返回的迭代器是fail-fast:如果集合在迭代器创建后的任何时间被修改,除了通过迭代器自己的remove 方法外,迭代器以任何方式抛出ConcurrentModificationException。因此,面对并发修改,迭代器快速而干净地失败,而不是在未来不确定的时间冒任意的、非确定性的行为。请注意,无法保证迭代器的快速失败行为
  • “结果集“entrySet”就是你要找的东西”。不是真的,因为问题特别提到它想要一个“keySet”。
【解决方案2】:

  1. 遍历entrySet
  2. 忽略空值
  3. 收集钥匙
        Map<String, String> map = new HashMap<>();
        map.entrySet().stream()
            .filter(e -> e.getValue() != null)
            .map(Entry::getKey)
            .collect(Collectors.toSet());

使用 for 循环

        Set<String> keys = new HashSet<>();
        for (Map.Entry<String, String> e : map.entrySet()) {
            if (e.getValue() != null) {
                keys.add(e.getKey());
            }
        }

【讨论】:

  • 不要像这样使用Objects.nonNull(),使用普通的旧!= null检查。正如javadoc 所说“此方法的存在是为了用作Predicate,这意味着它的存在是为了方便用作预期Predicate 的方法引用。
  • @Andreas,当然。感谢您分享信息。我会更新答案。
猜你喜欢
  • 2021-10-02
  • 2021-10-01
  • 2021-06-22
  • 2017-03-29
  • 2020-09-08
  • 1970-01-01
  • 2019-04-23
  • 1970-01-01
  • 2016-03-08
相关资源
最近更新 更多