查找map是否包含list/iterable中的任何键的有效方法

ccp*_*zza 14 java arrays iteration dictionary

我需要检查map是否包含列表中的任何键,如果是,则返回第一个匹配值.想到的天真方法是在两个嵌套循环中进行:

Map<String, String> fields = new HashMap<String, String>();
fields.put("a", "value a");
fields.put("z", "value z");
String[] candidates = "a|b|c|d".split("|");
for (String key : fields.keySet()){
    for (String candidate : candidates) {
        if (key.equals(candidate)){
            return fields.get(key);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

是否有更好,更有效的方式,可能依赖Java标准库?

Nim*_*sky 24

for(String candidate : candidates) {
 if(fields.containsKey(candidate)) {
  return fields.get(candidate)
 }
}
Run Code Online (Sandbox Code Playgroud)

如果空值可能在map中,并且只需要第一个检测到的键,则是最好的方法.


Bri*_*new 22

肯定是这样的:

for (String candidate : candidates) {
     String result = fields.get(key);
     if (result != null) {
         return result;
     }
}
Run Code Online (Sandbox Code Playgroud)

以上仅针对每个候选键执行一次地图查找.它避免了对存在加提取的单独测试,因为提取不存在的键只会给你一个空值.注意(感谢Slanec),有效密钥的空值与此解决方案的非存在密钥无法区分.

我不太明白你为什么要进行大小写转换,顺便说一句.

  • 这是有效的,但如果`null`是`Map`中的允许值,它可能会变得棘手. (9认同)
  • 有意思......我是否理解正确的想法是只使用`map.get()`一次而不是`map.contains()+ map.get()`因为这样可以避免第二次查找?那很整齐! (3认同)
  • @NimChimpsky retainAll是descructive. (3认同)
  • @ccpizza - 这是对的.请注意Slanec的警告.但是,地图中的空值 (2认同)
  • @ccpizza其实,是的,有一次,我想.在我们没有明确控制hashmap内容的应用程序中,因为它是用户的配置,我们需要捕获访问(但未更改)设置或重置为默认设置的情况.[无论如何,对此有一个问题.](http://stackoverflow.com/questions/3622007/why-is-it-useful-to-have-null-values-or-null-keys-in-hash -maps) (2认同)

mro*_*ini 9

在Java 8中,您可以拥有:

boolean exists = Arrays.stream(candidates).anyMatch(fields::containsKey);
Run Code Online (Sandbox Code Playgroud)

如果您只是想知道任何候选人是否是地图的关键.

如果你想知道第一个或任何你可以使用:

Arrays.stream(candidates).filter(fields::containsKey).findAny();
Run Code Online (Sandbox Code Playgroud)

要么

Arrays.stream(candidates).filter(fields::containsKey).findFirst();
Run Code Online (Sandbox Code Playgroud)

按照@ Klapsa2503上面的回答


Pet*_*ček 7

我的看法:

Map<String, String> fields = new HashMap<String, String>();
fields.put("a", "value a");
fields.put("z", "value z");
String[] candidates = "a|b|c|d".split("|");
for (String candidate : candidates) {
    if (fields.containsKey(candidate)) {
        return fields.get(candidate);
    }
}
Run Code Online (Sandbox Code Playgroud)


Kla*_*503 6

在Java 8中,您可以使用:

return candidates.stream()
            .filter(fields::containsKey)
            .findFirst()
            .map(fields::get)
            .orElse(null);
Run Code Online (Sandbox Code Playgroud)


Nik*_*sov 5

尝试

Set<String> keySet = new HashSet<String>(fields.keySet());    
keySet.retainAll(list);
Run Code Online (Sandbox Code Playgroud)

所以keySet应该有HashMap中列出的所有键

  • @Slanec,是的,这取决于OP是想获得所有密钥还是只需要第一个密钥. (3认同)
  • 我相信这是最短路的.但是,它可能不是最快的,因为循环结束于第一个找到的结果,但这继续其工作直到结束. (2认同)