2011-04-19 23 views
11

Bazı Anahtarlar verilen bir Haritadan tüm Değerleri almanın akıllı bir yolu var mı?Java/Guava'daki bazı Anahtarlar için bir Haritadaki tüm Değerleri Alın?

Böyle bir yöntemi istiyorum:

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

ya da zaten bir guava yoludur?

+0

Eğer gerçekten bir harita yerine arka değerlerin bir Koleksiyonu almak istiyor musunuz? Bunu inşa sürecinde, anahtarlar ve değerler arasındaki ilişkiyi kaybedersiniz. –

cevap

18

Bu yöntem işe istiyorum nasıl bağlıdır. Örneğin, mapA değildir keys elements) sadece göz ardı edilmelidir veya B) verilen değerler, koleksiyonunda null olarak temsil gereken veya C) bir hata olmalıdır? Ayrıca canlı bir görünüm ya da değerleri içeren ayrı bir koleksiyon isteyip istemediğinizi de düşünün.

A için, benim tercih olacaktır:

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

Bu harita çok daha büyük olsa bile, haritadaki aslında ve de nispeten verimli olmalıdır tuşlar için değerlere sonucu sınırlar İstediğiniz anahtarlardan daha. Elbette, bu sonucu ne yapmak istediğinize bağlı olarak başka bir koleksiyona kopyalamak isteyebilirsiniz.

B için, Functions.forMap(map, null) dışında @Michael Brewer-Davis'in çözümünü kullanırsınız.

C için, öncelikle map.keySet().containsAll(keys) olmadığını kontrol edin ve ardından @Michael Brewer-Davis'in çözümünü kullanmak false ederseniz bir hata ... ama sonra başka bir koleksiyona sonucu kopyalanan sürece farkında olmak isterdim map'dan bir girdiyi kaldırmak, bir noktada iade edilen koleksiyonu kullanarak kod için IllegalArgumentException neden olabilir.

+0

Boş değerlerle ilgilenmezseniz, A ve B'yi de birleştirebilirsiniz: Koleksiyon değerler = Collections2.filter (Collections2.transform (keys, Functions.forMap (map, null)), Predicates.notNull()); Bu, giriş başına yalnızca bir arama yapar (Predicates.in() ve bir başka işlevde bir arama yapmak yerine.forMap()) –

3

Guava'nın Maps.filteredKeys() numarasını kullanarak, istediğiniz tuşlarla eşleşen bir Predicate numaralı iletiyi kullanabilirsiniz, ancak bu, manuel yineleme işleminden daha iyi değildir.

3

kullanma guava: Collections2.transform(keys, Functions.forMap(map));

+1

Dönüştürülmüş koleksiyondaki bir öğeye haritadaki olmayan bir anahtara erişmeye çalışmanın 'IllegalArgumentException' ile sonuçlanacağını unutmayın; ancak mümkün olan durumlarda varsayılan olan bir aşırı yük tercih edilebilir. – ColinD

12

Sadece skaffman'ın cevabına katılıyorum, sadece onun sonucuyla değil (Bence bu, manuel yinelemeden daha iyi). İşte

dışarı yazıldığından:

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

, burada olmayan bir Guava sürümü:

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

Bunun için 'filterKeys' kullanarak kullandığım sorunlar şunlardır: A) 'map' anahtarının çok küçük olmasına rağmen' map' her girişinde yinelemeyi gerektirir (başka bir yöntem bir yöntem için daha az olası gibi görünüyor Bunun gibi) ve B) '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' ''''' hızlı bir 'içerir' uygulaması yok, eğer haritaya her giriş için bir kez çağrılması çağrı karmaşıklığı sırasını artıracaktır Verdiğim kodun hiçbiri bu konulara sahip değil. Guava olmayan sürüm için, bir döngünün daha iyi olacağını düşünüyorum ... sürümünüz, sonuç boş olsa bile, haritanın tüm kopyasını bellekte tutmayı gerektirir. – ColinD

İlgili konular