是否有一种聪明的方法可以从给定一些键的Map中获得所有值?
我想要一个这样的方法:
public static <K, V> Collection<V> getAll(Map<K, V> map, Collection<K> keys)
还是已经是番石榴了?
这取决于您希望该方法如何工作。例如,keys
中不在map
A)中的元素是否应该被忽略,或者它们B)应该在返回值集合中表示为null
,或者C)应该是一个错误?还要考虑是否需要实时视图或包含值的单独集合。
对于A,我的偏好是:
Collection<V> values = Collections2.transform(
Collections2.filter(keys, Predicates.in(map.keySet()),
Functions.forMap(map));
这将结果限制为映射中实际存在的键值,并且应该相对有效,即使映射比您想要的键集大得多。当然,您可能希望将该结果复制到另一个集合中,这取决于您想对它做什么。
对于B,除了Functions.forMap(map, null)
,您将使用@Michael Brewer-Davis的解决方案。
对于C,您首先要检查map.keySet().containsAll(keys)
并抛出错误,如果false
,然后使用@Michael Brewer-Davis的解决方案…但是要注意,除非您随后将结果复制到另一个集合中,否则从map
中删除条目可能会在某些时候导致使用返回集合的代码出现IllegalArgumentException
。
我同意skaffman的回答,只是不同意他的结论(我认为这比手动迭代要好)。
这里是拼出来的:
public static <K, V> Collection<V> getAll(Map<K, V> map, Collection<K> keys) {
return Maps.filterKeys(map, Predicates.in(keys)).values();
}
另外,这里有一个非guava版本(Java 8或更高版本):
public static <K, V> Collection<V> getAll(Map<K, V> map, Set<K> keys) {
return map.entrySet()
.stream()
.filter(e -> keys.contains(e.getKey()))
.map(Map.Entry::getValue)
.collect(Collectors.toList());
}
我认为您可以使用Guava的Maps.filteredKeys()
,传入与所需键匹配的Predicate
,但它实际上并不比手动迭代好。
使用番石榴:Collections2.transform(keys, Functions.forMap(map));
Java8 Streams:
keys.stream().map( map::get ).collect( Collectors.toList() );
或者如果您担心丢失键:
keys.stream().map( k -> map.getOrDefault( k, null ) ).filter(o -> o != null).collect( Collectors.toList() );
或者如果您需要多个线程工作(很少,请参阅@tkruse注释):
keys.parallelStream().map( map::get ).collect( Collectors.toList() );