查找映射是不是包含列表/可迭代项中的任何键的有效方法
Posted
技术标签:
【中文标题】查找映射是不是包含列表/可迭代项中的任何键的有效方法【英文标题】:Efficient way to find if map contains any of the keys from a list/iterable查找映射是否包含列表/可迭代项中的任何键的有效方法 【发布时间】:2012-12-13 15:49:38 【问题描述】:我需要检查一个映射是否包含列表中的任何键,如果包含则返回第一个匹配值。想到的幼稚方法是在两个嵌套循环中进行:
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 标准库?
【问题讨论】:
【参考方案1】:for(String candidate : candidates)
if(fields.containsKey(candidate))
return fields.get(candidate)
如果 null 值可能在 map 中,并且只需要第一个检测到的键,则最好的方法。
【讨论】:
【参考方案2】:肯定是这样的:
for (String candidate : candidates)
String result = fields.get(key);
if (result != null)
return result;
上面只对每个候选键执行 一个 映射查找。它避免了存在和提取的单独测试,因为提取不存在的键只会给你一个空值。请注意(感谢 Slanec)对于此解决方案,有效键的空值与不存在的键无法区分。
我不太明白你为什么要进行大小写转换,顺便说一句。
【讨论】:
这是尽可能高效的方法,但如果null
是 Map
中的允许值,则可能会变得棘手。
有趣...我是否正确理解这个想法是只使用一次map.get()
而不是map.contains() + map.get()
,因为这样可以避免第二次查找?这很整洁!
@NimChimpsky retainAll 具有描述性。
@ccpizza - 没错。请注意 Slanec 的警告。地图中的空值,但
@ccpizza 实际上,是的,一次,我想。在一个应用程序中,我们没有明确控制 hashmap 的内容,因为它是用户的配置,我们需要捕获设置被访问(但未更改)或重置为默认值的情况。 Anyway, there is a SO question for this.【参考方案3】:
在 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 回答
【讨论】:
【参考方案4】:我的看法:
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);
【讨论】:
【参考方案5】:在 Java 8 中你可以使用这个:
return candidates.stream()
.filter(fields::containsKey)
.findFirst()
.map(fields::get)
.orElse(null);
【讨论】:
【参考方案6】:试试
Set<String> keySet = new HashSet<String>(fields.keySet());
keySet.retainAll(list);
所以keySet
应该具有列表中提到的 HashMap 中的所有键
【讨论】:
我相信这是最短的方法。但是,它可能不是最快的,因为循环在第一个找到的结果处结束,但这会继续工作直到结束。 @Slanec,是的,这取决于 OP 是想要获取所有密钥还是只获取第一个。【参考方案7】:试一试
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
【讨论】:
【参考方案8】: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);
【讨论】:
注意:canList.contains 在时间上是线性的。【参考方案9】:如果您假设映射的键已经是小写,则可以使用单个循环,就像您假设查找值是小写一样。
【讨论】:
以上是关于查找映射是不是包含列表/可迭代项中的任何键的有效方法的主要内容,如果未能解决你的问题,请参考以下文章