Ottieni la chiave per un valore da una mappa Java

1. Introduzione

In questo breve tutorial, mostreremo tre diversi approcci per recuperare la chiave da una mappa per un dato valore. Discuteremo anche gli aspetti positivi e negativi delle varie soluzioni.

Per ulteriori informazioni sull'interfaccia della mappa , puoi consultare questo articolo.

2. Un approccio iterativo

L' interfaccia Map delle collezioni Java offre un metodo chiamato entrySet () . Restituisce tutte le voci o le coppie chiave-valore della mappa in un Set .

L'idea è di iterare su questo set di voci e restituire la chiave per la quale il valore corrisponde al valore fornito:

public  K getKey(Map map, V value) { for (Entry entry : map.entrySet()) { if (entry.getValue().equals(value)) { return entry.getKey(); } } return null; }

Tuttavia, potrebbe esserci la possibilità che più chiavi puntino allo stesso valore.

In tal caso, se viene trovato un valore corrispondente, aggiungiamo la chiave a un Set e continuiamo il ciclo. Alla fine, restituiamo il Set contenente tutte le chiavi desiderate:

public  Set getKeys(Map map, V value) { Set keys = new HashSet(); for (Entry entry : map.entrySet()) { if (entry.getValue().equals(value)) { keys.add(entry.getKey()); } } return keys; }

Sebbene questa sia un'implementazione molto semplice, confronta tutte le voci anche se tutte le corrispondenze vengono trovate dopo alcune iterazioni.

3. Un approccio funzionale

Con l'introduzione di Lambda Expressions in Java 8, possiamo farlo in un modo più flessibile e leggibile. Convertiamo il set di voci in un flusso e forniamo un lambda per filtrare solo le voci con il valore specificato.

Quindi usiamo il metodo map per restituire un flusso delle chiavi dalle voci filtrate:

public  Stream keys(Map map, V value) { return map .entrySet() .stream() .filter(entry -> value.equals(entry.getValue())) .map(Map.Entry::getKey); }

Il vantaggio di restituire un flusso è che può soddisfare un'ampia gamma di esigenze del cliente. Il codice chiamante può richiedere solo una chiave o tutte le chiavi che puntano al valore fornito. Poiché la valutazione di un flusso è pigra, il client può controllare il numero di iterazioni in base ai suoi requisiti.

Inoltre, il client può convertire il flusso in qualsiasi raccolta utilizzando un raccoglitore appropriato:

Stream keyStream1 = keys(capitalCountryMap, "South Africa"); String capital = keyStream1.findFirst().get(); Stream keyStream2 = keys(capitalCountryMap, "South Africa"); Set capitals = keyStream2.collect(Collectors.toSet());

4. Utilizzo delle collezioni Apache Commons

Le idee di cui sopra non sarebbero molto utili se avessimo bisogno di chiamare le funzioni molto frequentemente per una particolare mappa . Itererà inutilmente il set delle sue chiavi ancora e ancora.

In questo scenario, il mantenimento di un'altra mappa di valori per le chiavi avrebbe più senso in quanto richiederà tempo costante per recuperare la chiave per un valore.

La libreria Commons Collections di Apache fornisce una mappa bidirezionale chiamata BidiMap . Ha un metodo chiamato getKey () per recuperare una chiave per un dato valore:

BidiMap capitalCountryMap = new DualHashBidiMap(); capitalCountryMap.put("Berlin", "Germany"); capitalCountryMap.put("Cape Town", "South Africa"); String capitalOfGermany = capitalCountryMap.getKey("Germany");

Tuttavia, BidiMap impone una relazione 1: 1 tra le sue chiavi e valori . Se proviamo a inserire una coppia chiave-valore per cui il valore esiste già nella mappa, rimuove la vecchia voce. In altre parole, aggiorna la chiave rispetto al valore.

Inoltre, richiede una maggiore quantità di memoria per mantenere la mappa inversa.

Maggiori dettagli su come usare una BidiMap sono in questo tutorial.

5. Utilizzo di Google Guava

Possiamo utilizzare un'altra mappa bidirezionale chiamata BiMap trovata in Guava sviluppata da Google. Questa classe fornisce un metodo chiamato inverse () per ottenere la mappa della chiave valore o la mappa inversa per recuperare la chiave in base a un dato valore:

HashBiMap capitalCountryMap = HashBiMap.create(); capitalCountryMap.put("Berlin", "Germany"); capitalCountryMap.put("Cape Town", "South Africa"); String capitalOfGermany = capitalCountryMap.inverse().get("Germany");

Come BidiMap , anche BiMap non consente più chiavi che si riferiscono allo stesso valore . Se proviamo a fare un tale tentativo, viene generata un'eccezione java.lang.IllegalArgumentException .

Inutile dire che BiMap utilizza anche una notevole quantità di memoria in quanto deve memorizzare la mappa inversa all'interno. Se sei interessato a saperne di più su BiMap , puoi dare un'occhiata a questo tutorial.

6. Conclusione

In questo breve articolo, abbiamo discusso alcuni metodi per recuperare la chiave di una mappa dato il valore. Ogni approccio ha i suoi pro e contro. Dovremmo sempre considerare i casi d'uso e scegliere quello più appropriato in base alla situazione.

Il codice sorgente completo per il tutorial sopra è disponibile su GitHub.