2011-04-19 61 views
11

有没有一种智能的方法可以从给出某些键的Map中获取所有值?在Java/Guava中从某个地图获取所有的值?

我想这样的方法:

public static <K, V> Collection<V> getAll(Map<K, V> map, Collection<K> keys) 

或已经是一个番石榴方式?

+0

你真的想找回值的集合,而不是一个地图?在构建过程中,您会失去键和值之间的关联。 – 2015-04-09 15:57:42

回答

18

这取决于你怎么想的方法工作。例如,应不在mapA)在keys元件只是被忽略还是应该B)被表示为在返回的值集合null或应该C)是错误?还要考虑您是要实时查看还是包含值的单独集合。

对于一个,我的偏好是:

Collection<V> values = Collections2.transform(
    Collections2.filter(keys, Predicates.in(map.keySet()), 
    Functions.forMap(map)); 

这限制了结果值,实际上是在地图,应该是比较有效的,以及按键,即使在地图大得多比你想要的一组键。当然,您可能希望将结果复制到另一个集合,具体取决于您想要使用的结果。

对于,你会使用@迈克尔 - 布鲁尔 - 戴维斯的解决方案,除了与Functions.forMap(map, null)

对于Ç,你首先要检查map.keySet().containsAll(keys),并抛出一个错误,如果false,然后用@迈克尔 - 布鲁尔 - 戴维斯的解决方案,但请注意,除非你再在另一个集合中复制的结果,从map中删除条目可能导致IllegalArgumentException用于在某个点使用返回的集合的代码。

+0

如果你不关心空值,你也可以结合A和B: 集合 values = Collections2.filter(Collections2.transform(keys,Functions.forMap(map,null)),Predicates.notNull());这只对每个条目进行一次查找(而不是在Predicates.in()中进行一次查找,而在函数中进行另一次查找。forMap()) – 2011-04-20 23:34:11

3

你可以,我想使用番石榴的Maps.filteredKeys(),传递一个Predicate,它与你想要的键匹配,但它并不比人工迭代更好。

3

使用番石榴: Collections2.transform(keys, Functions.forMap(map));

+1

请注意,尝试访问转换后的集合中某个不在映射中的键的元素将导致“IllegalArgumentException”,尽管如果可能的话,使用默认值的重载可能更可取。 – ColinD 2011-04-19 17:41:05

12

我同意skaffman的回答,只是没有他的结论(我认为这比手动迭代更好)。

这是阐明:

public static <K, V> Collection<V> getAll(Map<K, V> map, Collection<K> keys) { 
    return Maps.filterKeys(map, Predicates.in(keys)).values(); 
} 

而且,这里有一个非番石榴版本:

public static <K, V> Collection<V> getAll(Map<K, V> map, Collection<K> keys) { 
    Map<K, V> newMap = new HashMap<K, V>(map); 
    newMap.keySet().retainAll(keys); 
    return newMap.values(); 
} 
+2

我在使用'filterKeys'时遇到的问题是:A)它需要遍历'map'的每个条目,即使'keys'小得多(反过来,其他方法似乎不太可能用于方法像这样); B)如果'keys'集合没有一个快速的'contains'实现,为map中的每个条目调用一次将会增加调用的复杂性。我给出的代码没有这些问题。对于非Guava版本,我认为循环会更好......您的版本需要在内存中保留整个映射副本,即使结果为空。 – ColinD 2011-04-20 21:30:28

相关问题