从Map中获取Java/Guava中某些键的所有值



是否有一种聪明的方法可以从给定一些键的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() );

最新更新