【问题标题】:Best way to check a list of values present in a map检查地图中存在的值列表的最佳方法
【发布时间】:2019-10-03 00:59:18
【问题描述】:

我有一个包含一些值的Collection

Collection<String> myList = new ArrayList<String>();
myList.add("a");
myList.add("b");
myList.add("c");

我创建了一个Map,它有一些值:

Map<String, String> myMap = new HashMap<String, String>();
myMap.put("r", "r");
myMap.put("s","m");
myMap.put("t", "n");
myMap.put("a", "o");

我想检查列表中的值是否在地图中作为键存在?我知道使用 Java 的方法是遍历列表并使用 myMap.containsKey() 检查地图是否包含该特定值。我想知道是否有任何使用流或 for-each 的东西可以节省我的代码行或有效的方法!感谢您考虑它。

编辑: 我想存储myList 中存在的所有元素,而myMap 中不存在这些元素。所以我的输出可以是一个列表,例如在这种情况下[b,c]

【问题讨论】:

  • myList.forEach(x -&gt; System.out.println(map.containsKey(x))) 但它可能会为您节省 2 行代码?
  • 为什么要把事情复杂化?为什么不直接使用myMap.keySet().containsAll(myList);
  • 可以从列表中创建一个Set,然后使用带有keySet 参数的retainAll 方法。然后就有可能知道列表中的哪些元素是映射中的键。
  • @Eugene True,但这需要 OP 澄清。
  • @SiddharthShankar 这里的预期结果是什么?您想知道列表中的 any 元素是用作映射键还是 all 都用作键?

标签: java dictionary collections java-8 hashmap


【解决方案1】:

使用 Streams 您可以执行以下操作:

List<String> result = myList.stream()                
                            .filter(myMap::containsKey)
                            .collect(Collectors.toList());

结果列表将包含在地图中作为键存在的值。

如果您想将它们打印出来,您可以这样做:

result.forEach(System.out::println);

【讨论】:

  • 您可以使用Map.containsKey: myList.stream().filter(myMap::containsKey).collect(Collectors.toSet()) 更简洁地做到这一点
  • @xbakesx 是的。我将编辑以包含您的建议。
【解决方案2】:
Set<String> mySet = new HashSet<String>(myList);
myMap.keySet().containsAll(set);

这能回答你的问题吗?

编辑后:鉴于上述情况,您可以使用以下问题之一的答案获得两组之间的键差异:- What is the best way get the symmetric difference between two sets in java?Getting the difference between two sets

【讨论】:

  • myList 复制到HashSet 是没有意义的。只做myMap.keySet().containsAll(myList); 就足够了。除非您要通过mySet.removeAll(myMap.keySet()) 获取丢失的密钥。但除非你真的这样做,否则HashSet 已经过时了。
  • 这里将set和list传递给containAll方法是有区别的 myMap.keySet().containsAll(set);正如 containsAll 方法本身的 javadocs 中所述: /* 如果此集合包含 * 指定集合的​​所有元素,则返回 true。如果指定的集合也是一个集合,如果它是这个集合的一个子集,这个*方法返回true。**/
【解决方案3】:

...列表中的值是否作为键存在于映射中?

据我了解,您需要验证myList 中的所有元素是否作为myMap 的键存在所有。使用Stream::allMatch 方法:

myMap.keySet().stream()
              .allMatch(myList::contains);

... 等同于:

myList.keySet().containsAll(myMap);

编辑:我想存储myList 中存在的所有元素,而myMap 中不存在这些元素。所以我的输出可以是一个列表,例如在这种情况下 [b,c]。

您不想将所有元素都存储在myList 中,因为它们已经被填满了。您希望使用List::retainAll保留这些元素。

myList.retainAll(myMap.keySet());

打印出myList 的结果将仅生成键,这些键已在原始myList 中找到,并且还作为myMap 的键。

【讨论】:

  • 我认为方法应该相反:myList.stream() .allMatch(myMap::containsKey) 因为地图中的键不需要全部出现在列表中。
  • 是的,这就是我的代码所做的 :) 请注意,在这两种情况下,myMap 中的每个键都会检查是否存在于 myList 中。
  • 通过问题中的编辑,OP 可能正在寻找removeIf 而不是retainAll
  • myMap.keySet().stream() .allMatch(myList::contains); myList.keySet().containsAll(myMap); 相同。 @Laguh 建议的myList.stream() .allMatch(myMap::containsKey)。同样,“only the keys, that have found”与“which are not there”不同。对于 OP 所描述的内容,removeAll 将是正确的,而不是retainAll
  • @Naman 或removeAll。如果您要检查复杂的条件,removeIf 方法很不错,但如果仅涉及另一个集合中的存在,好的旧批量数据方法就足够了。
【解决方案4】:

对于:我想存储 myList 中存在的所有元素 myMap 中没有。所以我的输出可以是一个列表,例如在这种情况下 [b,c]

创建一个重复的 myList 并删除所有 myMap 的键

        Collection<String> newList = new ArrayList<>(myList);
        newList.removeAll(myMap.keySet());
        System.out.println(newList);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-10
    • 2022-06-06
    • 2017-08-26
    • 2010-10-28
    • 2022-12-15
    • 2010-10-01
    相关资源
    最近更新 更多