2011-04-19 63 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

相關問題