Ottenere tutti i Valori di una Mappa, per alcuni Tasti in Java/Guava?

C’è un modo intelligente per ottenere tutti i Valori da una Mappa dato alcune Chiavi?

Vorrei un metodo come questo:

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

o è già un guava modo?

  • Vuoi davvero tornare un insieme di valori, piuttosto che una Mappa? Nel processo di costruzione di che, si perderebbe l’associazione tra chiavi e valori.

 

5 Replies
  1. 18

    Questo dipende da come si desidera che il metodo di lavoro. Per esempio, nel caso di elementi in keys che non sono in map A) solo di essere ignorato o dovrebbero B) essere rappresentato come null nel restituito valori di raccolta o che dovrebbero C) essere un errore? Anche prendere in considerazione se si desidera che il live view o la raccolta separata contenente i valori.

    Per Un, la mia preferenza sarebbe:

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

    Questo limita il risultato di valori per le chiavi, che sono in realtà la mappa e dovrebbe essere abbastanza efficiente, anche se la mappa è molto grande rispetto al set di chiavi che si desidera. Naturalmente, se si desidera copiare il risultato in un’altra collezione a seconda di cosa si vuole fare con esso.

    Per B, devi utilizzare @Michael Brewer-Davis soluzione se non con Functions.forMap(map, null).

    Per C, devi prima verificare che map.keySet().containsAll(keys) e lanciare un messaggio di errore se false, quindi utilizzare @Michael Brewer-Davis soluzione… ma essere consapevoli del fatto che a meno che tu poi copiato il risultato in un’altra raccolta, la rimozione di una voce da map potrebbe causare un IllegalArgumentException per il codice utilizzando l’insieme restituito a un certo punto.

    • Se non si preoccupano i valori null, si potrebbe anche combinare A e B: Collection<V> valori = Collections2.filtro(Collections2.di trasformazione(tasti, Funzioni.forMap(mappa, null)), Predicati.notNull()); Questa è solo una ricerca per voce (invece di fare una ricerca in Predicati.in() e un altro in Funzioni.forMap())
  2. 13

    Sono d’accordo con skaffman risposta, non solo con la sua conclusione, credo che questo è meglio di un manuale di iterazione).

    Qui che è scritto:

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

    Inoltre, qui si tratta di un non-Guava versione:

    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();
    }
    • I problemi che ho con l’utilizzo di filterKeys per questo sono che A) si richiede di scorrere ogni voce di map, anche se keys è molto più piccolo (e viceversa sembra meno probabile per un metodo come questo), e B) se il keys raccolta non dispone di un veloce contains attuazione, chiamata una volta sola per ogni voce nella mappa aumenterà l’ordine di complessità della chiamata. Il codice che ho dato non ha uno di questi problemi. Per non Guava versione, penso che un ciclo sarebbe meglio… la tua versione richiede di mantenere una copia intera della mappa in memoria anche se il risultato è vuoto.
  3. 3

    Si potrebbe, suppongo che l’uso di Guava è Maps.filteredKeys(), passando in un Predicate che corrisponde al tuo tasti desiderati, ma non è davvero niente di meglio di manuale di iterazione.

  4. 3

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

    • Essere consapevoli del fatto che il tentativo di accedere a un elemento in trasformata di raccolta per una chiave che non è nella mappa si tradurrà in un IllegalArgumentException però… il sovraccarico con un valore predefinito può essere preferibile, se possibile.
  5. 0

    Java8 Flussi:

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

    O se sei preoccupato per la mancanza di tasti:

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

    O se la mappa è thread-safe e possibilità di grandi:

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

Lascia un commento