Получить все значения из карты для некоторых ключей в Java / Guava? - PullRequest
11 голосов
/ 19 апреля 2011

Есть ли умный способ получить все значения из карты с заданными ключами?

Я бы хотел такой метод:

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

или это уже способ гуавы?

Ответы [ 5 ]

18 голосов
/ 19 апреля 2011

Это зависит от того, как вы хотите, чтобы метод работал. Например, следует ли просто игнорировать элементы в keys, которые не входят в map A) , или они B) должны быть представлены как null в коллекции возвращаемых значений или это C) должно быть ошибкой? Также подумайте, хотите ли вы просматривать в реальном времени или отдельную коллекцию, содержащую значения.

Для A я бы предпочел:

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

Это ограничивает результат значениями для ключей, которые фактически находятся на карте и должны быть относительно эффективными, даже если карта намного больше, чем набор ключей, который вы хотите. Конечно, вы можете скопировать этот результат в другую коллекцию, в зависимости от того, что вы хотите с ней сделать.

Для B вы бы использовали решение @Michael Brewer-Davis, кроме как с Functions.forMap(map, null).

Для C вы сначала захотите проверить это map.keySet().containsAll(keys) и сгенерировать ошибку, если false, а затем использовать решение @Michael Brewer-Davis ... но учтите, что если только вы скопировал результат в другую коллекцию, удаление записи из map может вызвать IllegalArgumentException для кода, использующего возвращенную коллекцию в некоторый момент.

13 голосов
/ 20 апреля 2011

Я согласен с ответом Скаффмана, но не с его заключением (я думаю, что это лучше, чем ручная итерация).

Здесь прописано:

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();
}
3 голосов
/ 19 апреля 2011

Использование гуавы: Collections2.transform(keys, Functions.forMap(map));

3 голосов
/ 19 апреля 2011

Вы могли бы, я полагаю, использовать Maps.filteredKeys() в Guava, передавая Predicate, который соответствует вашим желаемым ключам, но на самом деле это не лучше, чем ручная итерация.

0 голосов
/ 31 июля 2018

Java8 Streams:

keys.stream().map( map::get ).collection( Collection.toList() );

Или, если вас беспокоит отсутствие ключей:

keys.stream().map( k -> map.getOrDefault( k, null ) ).collection( Collection.toList() );

Или, если ваша карта поточно-ориентирована и имеет большие возможности:

keys.parallelStream().map( map::get ).collection( Collection.toList() );
...