2012-12-28 35 views
6

我需要检查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); 
     } 
    } 
} 

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

回答

19

当然是这样的:

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

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

我不明白你为什么要执行案例转换,顺便说一句。

+8

这是有效的,因为它可以得到的,但是如果'null'是'Map'中的允许值,它可能会变得棘手。 –

+3

有趣...我的理解是否正确,只是使用'map。get()'一次而不是'map.contains()+ map.get()',因为这会避免第二次查找?那很整齐! – ccpizza

+3

@NimChimpsky retainAll是descructive。 –

20
for(String candidate : candidates) { 
if(fields.containsKey(candidate)) { 
    return fields.get(candidate) 
} 
} 

如果空值可能在映射中,并且只需要第一个检测到的密钥,那么这是最好的方法。

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); 
    } 
} 
1
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("|"); 
List<String> canList = Arrays.asList(candidates); 
for (String key : fields.keySet()){ 

if (canList .contains(key)) { 
return fields.get(key); 
} 

} 
+1

**注**:canList.contains在时间上是线性的。 – Srinivas

2

尝试为

List list= Arrays.asList(1, 2, 3); 
    HashMap map = new HashMap(); 
    map.put(1, 1); 
    map.put(3, 3); 
    Set set = new HashSet(map.keySet()); 
    set.retainAll(list); 
    System.out.println(set); 
    Object e = set.isEmpty() ? null : set.iterator().next(); 
    System.out.println(e); 

输出

[1, 3] 
1 
5

尝试

Set<String> keySet = new HashSet<String>(fields.keySet());  
keySet.retainAll(list); 

所以keySet应该具有的HashMap它们在列表中提及的所有键

+2

这是,我相信,最短的路。然而,它可能不是最快的,因为循环在第一个结果结束时结束,但是这继续其工作直到结束。 –

+3

@Slanec,是的,它取决于OP是否想要获得所有密钥或只是第一个。 –

1

如果您假定地图的键已经是小写字母,则可以使用单个循环,这与您假设查询值采用小写字母的方式相同。

4

在Java 8,你可以使用这个:

return candidates.stream() 
      .filter(fields::containsKey) 
      .findFirst() 
      .map(fields::get) 
      .orElse(null); 
5

在Java 8,你可以有这样的:

boolean exists = Arrays.stream(candidates).anyMatch(fields::containsKey); 

如果你只是想知道,如果任何候选人的关键是地图。

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

Arrays.stream(candidates).filter(fields::containsKey).findAny(); 

Arrays.stream(candidates).filter(fields::containsKey).findFirst(); 

按@ Klapsa2503回答上述

相关问题