Hashmap Java: come ottenere la chiave dal valore?


450

Se ho il valore "foo"e una HashMap<String> ftwper la quale ftw.containsValue("foo")ritorna true, come posso ottenere la chiave corrispondente? Devo passare in rassegna l'hashmap? Qual è il modo migliore per farlo?


72
Si noti che non esiste una singola chiave corrispondente - potrebbero esserci più chiavi associate allo stesso valore.
CPerkins,

1
@CPerkins ma per hashmap come <strFilename, Reader> e molti altri da 1 a 1, è molto utile.
Aquarius Power il

se hai una piccola collezione di articoli, considera la possibilità di creare costanti public static final String TIME = "time";eproperties.put(TIME, PbActivityJpa_.time);
Basheer AL-MOMANI,

probabilmente questo potrebbe aiutarti a ottenere i dati dalla mappa e puoi anche eseguire un qualche tipo di elaborazione. frugalisminds.com/java/java-8-stream-map-examples
Sanjay-Dev

Risposte:


215

Se si sceglie di utilizzare la libreria Commons Collections anziché l'API Java Collections standard, è possibile ottenerlo facilmente.

Il interfaccia BidiMap nella libreria Collezioni è una mappa bidirezionale, che consente di mappare una chiave su un valore (come le mappe normali) e anche di mappare un valore su una chiave, consentendo così di eseguire ricerche in entrambe le direzioni. L'ottenimento di una chiave per un valore è supportato dal metodo getKey () .

Esiste tuttavia un avvertimento: le mappe bidi non possono avere più valori associati a chiavi e, quindi, a meno che il set di dati non abbia mappature 1: 1 tra chiavi e valori, non è possibile utilizzare le bidimap.

Aggiornare

Se si desidera fare affidamento sull'API Java Collections, sarà necessario garantire la relazione 1: 1 tra chiavi e valori al momento dell'inserimento del valore nella mappa. Questo è più facile a dirsi che a farsi.

Una volta assicurato ciò, utilizzare il metodo entrySet () per ottenere l'insieme di voci (mappature) nella Mappa. Dopo aver ottenuto il set il cui tipo è Map.Entry , scorrere le voci, confrontando il valore memorizzato con quello previsto e ottenere la chiave corrispondente .

Aggiornamento n. 2

Il supporto per le mappe bidi con generici può essere trovato in Google Guava e nelle biblioteche delle raccolte comuni (la seconda non è un progetto Apache). Grazie a Esko per aver sottolineato il supporto generico mancante nelle collezioni Apache Commons. L'uso di raccolte con generici rende il codice più gestibile.


23
... e se ti piacciono i generici e tutta quella roba moderna, Google Collections ha BiMap dove puoi ottenere la chiave corrispondente al valore specificato chiamando biMap.inverse (). get (value);
Esko,

1
Sì, le collezioni Apache Commons non supportano i generici. Tuttavia, ci sono raccolte di Google come hai sottolineato (che non uso ancora - nessuna versione 1.0 ancora), e ci sono le raccolte comuni refactored con supporto per Generics. Lo troverai come progetto Sourceforge @ sourceforge.net/projects/collections
Vineet Reynolds

2
Le raccolte Google non sono una versione refactored delle raccolte comuni.
whiskeysierra,

12
@whiskeysierra: Non penso che nessuno lo stia dicendo (al momento).
Huff,

2
Le raccolte Apache ora supportano generics commons.apache.org/proper/commons-collections/javadocs/…
kervin

603

Se la struttura dei dati ha una mappatura multi -to-one tra chiavi e valori, è necessario scorrere le voci e selezionare tutte le chiavi adatte:

public static <T, E> Set<T> getKeysByValue(Map<T, E> map, E value) {
    Set<T> keys = new HashSet<T>();
    for (Entry<T, E> entry : map.entrySet()) {
        if (Objects.equals(value, entry.getValue())) {
            keys.add(entry.getKey());
        }
    }
    return keys;
}

In caso di relazione uno a uno , puoi restituire la prima chiave corrispondente:

public static <T, E> T getKeyByValue(Map<T, E> map, E value) {
    for (Entry<T, E> entry : map.entrySet()) {
        if (Objects.equals(value, entry.getValue())) {
            return entry.getKey();
        }
    }
    return null;
}

In Java 8:

public static <T, E> Set<T> getKeysByValue(Map<T, E> map, E value) {
    return map.entrySet()
              .stream()
              .filter(entry -> Objects.equals(entry.getValue(), value))
              .map(Map.Entry::getKey)
              .collect(Collectors.toSet());
}

Inoltre, per gli utenti di Guava, BiMap può essere utile. Per esempio:

BiMap<Token, Character> tokenToChar = 
    ImmutableBiMap.of(Token.LEFT_BRACKET, '[', Token.LEFT_PARENTHESIS, '(');
Token token = tokenToChar.inverse().get('(');
Character c = tokenToChar.get(token);

3
Puoi dire qualcosa sulla performance? Cosa sarà più ottimizzato? Questo o BidiMap?
tasomaniaco

Ho pensato alla stessa soluzione, l'ho votata ovviamente ma dubito della sua efficienza quando si tratta di Collezioni davvero grandi.
Arjacsoh,

3
stackoverflow.com/questions/4553624/hashmap-get-put-complexity HashMap ha complessità temporale o(1). Se stai ripetendo i valori, la performance verrà annullata. Se vuoi una relazione e hai better performanceuna one-onerelazione, puoi usare another mapwherevalue is a key
veer7,

3
Consiglio di sostituirlo .filter(entry -> entry.getValue().equals(value))con poiché non è stata fatta alcuna dichiarazione sull'abilità. Inoltre, è possibile sostituire con.filter(entry ->Objects.equals(entry.getValue(), value))null.map(entry -> entry.getKey()).map(Map.Entry::getKey)
Holger

sto avendo difficoltà a capire la notazione <T, E> prima di Set <T> getKeysByValue () ... qual è il punto .... modo diverso di farlo senza usarlo? grazie
ponderingdev il

76
public class NewClass1 {

    public static void main(String[] args) {
       Map<Integer, String> testMap = new HashMap<Integer, String>();
        testMap.put(10, "a");
        testMap.put(20, "b");
        testMap.put(30, "c");
        testMap.put(40, "d");
        for (Entry<Integer, String> entry : testMap.entrySet()) {
            if (entry.getValue().equals("c")) {
                System.out.println(entry.getKey());
            }
        }
    }
}

Alcune informazioni aggiuntive ... Potrebbe esserti utile

Il metodo sopra potrebbe non essere buono se la tua hashmap è davvero grande. Se la tua hashmap contiene una chiave univoca per la mappatura di valori univoci, puoi conservare un'altra hashmap che contiene una mappatura da Valore a Chiave.

Cioè devi mantenere due hashmap

1. Key to value

2. Value to key 

In tal caso è possibile utilizzare la seconda hashmap per ottenere la chiave.


19

Penso che le tue scelte siano

  • Usa un'implementazione della mappa creata per questo, come la BiMap di Google. Tieni presente che BiMap delle raccolte Google richiede valori univoci di valori e chiavi, ma offre prestazioni elevate in entrambe le direzioni
  • Mantenere manualmente due mappe - una per chiave -> valore e un'altra mappa per valore -> chiave
  • Scorrere entrySet()i tasti e per trovare le chiavi che corrispondono al valore. Questo è il metodo più lento, poiché richiede di scorrere l'intera raccolta, mentre gli altri due metodi non lo richiedono.

19

È possibile inserire sia la chiave, la coppia di valori e il suo inverso nella struttura della mappa

map.put("theKey", "theValue");
map.put("theValue", "theKey");

L'uso di map.get ("theValue") restituirà quindi "theKey".

È un modo rapido e sporco che ho creato mappe costanti, che funzionerà solo per alcuni set di dati selezionati:

  • Contiene solo da 1 a 1 coppia
  • L'insieme di valori è disgiunto dall'insieme di chiavi (1-> 2, 2-> 3 lo interrompe)

4
Questo non è proprio corretto. Ciò non richiede solo 1-1, ma anche che l'insieme di valori è disgiunto dall'insieme di chiavi. Non puoi applicarlo alla mappa biiettiva {1 -> 2, 2 -> 3}: 2 è sia un valore che una chiave.
Luis A. Florit,

15

Decora la mappa con la tua implementazione

class MyMap<K,V> extends HashMap<K, V>{

    Map<V,K> reverseMap = new HashMap<V,K>();

    @Override
    public V put(K key, V value) {
        // TODO Auto-generated method stub
        reverseMap.put(value, key);
        return super.put(key, value);
    }

    public K getKey(V value){
        return reverseMap.get(value);
    }
}

Penso che questo sia un approccio interessante, anche se dal momento che la relazione deve essere 1: 1, mi sbarazzerei del tutto di HashMap e implementerei invece l'interfaccia Map <K, V> in modo da evitare duplicati di entrambi, valori e chiavi.
Fran Marzoa,

11

Non esiste una risposta inequivocabile, poiché più chiavi possono essere associate allo stesso valore. Se stai applicando l'unicità con il tuo codice, la soluzione migliore è quella di creare una classe che utilizza due hashmap per tracciare i mapping in entrambe le direzioni.


11

Per trovare tutte le chiavi associate a quel valore, scorrere tra tutte le coppie nell'hashmap, usando map.entrySet().


4
Questa soluzione è terribilmente intensa, al punto da non essere pratica su grandi HashMap.
Joehot200

10

Utilizzando Java 8:

ftw.forEach((key, value) -> {
    if (value.equals("foo")) {
        System.out.print(key);
    }
});

6
value=="foo" questo non funzionerà. equalsdovrebbe essere usato per confrontare le stringhe.
Anton Balaniuc

@Anton, vero a meno che non valuesia stato internato.
frododot,

9

Se costruisci la mappa con il tuo codice, prova a mettere insieme chiave e valore nella mappa:

public class KeyValue {
    public Object key;
    public Object value;
    public KeyValue(Object key, Object value) { ... }
}

map.put(key, new KeyValue(key, value));

Quindi quando hai un valore, hai anche la chiave.


3
Intelligente, ma cosa succede se ci sono 2 o più oggetti KeyValue contenenti lo stesso valore? Quale chiave si dovrebbe scegliere?
Vineet Reynolds,

2
@Vineet, non vedo come questo approccio risolva la domanda del PO. cosa intendevi con "Quindi quando hai un valore, hai anche la chiave"?
Qiang Li,

9

Penso che questa sia la soluzione migliore, indirizzo originale: Java2s

    import java.util.HashMap;
    import java.util.Map;

        public class Main {

          public static void main(String[] argv) {
            Map<String, String> map = new HashMap<String, String>();
            map.put("1","one");
            map.put("2","two");
            map.put("3","three");
            map.put("4","four");

            System.out.println(getKeyFromValue(map,"three"));
          }


// hm is the map you are trying to get value from it
          public static Object getKeyFromValue(Map hm, Object value) {
            for (Object o : hm.keySet()) {
              if (hm.get(o).equals(value)) {
                return o;
              }
            }
            return null;
          }
        }

Un facile utilizzo: se inserisci tutti i dati in hasMap e hai item = "Automobile", quindi stai cercando la sua chiave in hashMap. questa è una buona soluzione.

getKeyFromValue(hashMap, item);
System.out.println("getKeyFromValue(hashMap, item): "+getKeyFromValue(hashMap, item));

7

Temo che dovrai solo iterare la tua mappa. Il più breve che potessi inventare:

Iterator<Map.Entry<String,String>> iter = map.entrySet().iterator();
while (iter.hasNext()) {
    Map.Entry<String,String> entry = iter.next();
    if (entry.getValue().equals(value_you_look_for)) {
        String key_you_look_for = entry.getKey();
    }
}

6
for(int key: hm.keySet()) {
    if(hm.get(key).equals(value)) {
        System.out.println(key); 
    }
}

6

Sembra che il modo migliore sia quello di scorrere le voci usando map.entrySet()poiché map.containsValue()probabilmente lo fa comunque.


Sì, è esattamente quello che fa. Ma ovviamente ritorna vero non appena trova un valore per il quale .equals è vero, al contrario di ciò che probabilmente OP dovrà fare.
CPerkins,

1
Bene, iterando le voci può tornare con chiave non appena trova anche un valore corrispondente. Le partite multiple non sembravano essere una preoccupazione.
Jonas K,

6

Per l'API di targeting per sviluppo Android <19, la soluzione di relazione one-to-one Vitalii Fedorenko non funziona perché Objects.equalsnon è implementata. Ecco una semplice alternativa:

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

Questa soluzione funziona per me; sviluppo anche per una versione archeologica di Android, nel mio caso per ottenere la chiave di un marcatore di Google Map in una mappa in un evento "onMarkerClick". Iterazione della voceSet funziona; ma iterando le chiavi e abbinandole alle voci con get (), e confrontando l'output, non lo ha fatto.
Toby Wilson,

3

È possibile utilizzare quanto segue:

public class HashmapKeyExist {
    public static void main(String[] args) {
        HashMap<String, String> hmap = new HashMap<String, String>();
        hmap.put("1", "Bala");
        hmap.put("2", "Test");

        Boolean cantain = hmap.containsValue("Bala");
        if(hmap.containsKey("2") && hmap.containsValue("Test"))
        {
            System.out.println("Yes");
        }
        if(cantain == true)
        {
            System.out.println("Yes"); 
        }

        Set setkeys = hmap.keySet();
        Iterator it = setkeys.iterator();

        while(it.hasNext())
        {
            String key = (String) it.next();
            if (hmap.get(key).equals("Bala"))
            {
                System.out.println(key);
            }
        }
    }
}

È bello che tu voglia fornire cose utili, ma non dovrebbe essere una risposta "solo codice" e il codice stesso non dovrebbe essere pieno di odori di codice, neanche.
Tom,

2

Sì, è necessario scorrere ciclicamente l'hashmap, a meno che non si attui qualcosa sulla falsariga di ciò che suggeriscono queste varie risposte. Piuttosto che armeggiare con entrySet, otterrei semplicemente keySet (), ripeterei quel set e conserverei la (prima) chiave che ti dà il valore corrispondente. Se hai bisogno di tutte le chiavi che corrispondono a quel valore, ovviamente devi fare tutto.

Come suggerisce Jonas, questo potrebbe già essere ciò che sta facendo il metodo IncludesValue, quindi potresti semplicemente saltare quel test tutti insieme e fare l'iterazione ogni volta (o forse il compilatore eliminerà già la ridondanza, chi lo sa).

Inoltre, rispetto alle altre risposte, se appare la tua mappa inversa

Map<Value, Set<Key>>

puoi gestire mappature di valori chiave> non univoci, se hai bisogno di tale capacità (districandole da parte). Ciò si integrerebbe perfettamente in una qualsiasi delle soluzioni che la gente suggerisce qui usando due mappe.


2

È possibile ottenere la chiave utilizzando i valori utilizzando il seguente codice.

ArrayList valuesList = new ArrayList();
Set keySet = initalMap.keySet();
ArrayList keyList = new ArrayList(keySet);

for(int i = 0 ; i < keyList.size() ; i++ ) {
    valuesList.add(initalMap.get(keyList.get(i)));
}

Collections.sort(valuesList);
Map finalMap = new TreeMap();
for(int i = 0 ; i < valuesList.size() ; i++ ) {
    String value = (String) valuesList.get(i);

    for( int j = 0 ; j < keyList.size() ; j++ ) {
        if(initalMap.get(keyList.get(j)).equals(value)) {
            finalMap.put(keyList.get(j),value);
        }   
    }
}
System.out.println("fianl map ---------------------->  " + finalMap);

2
public static class SmartHashMap <T1 extends Object, T2 extends Object> {
    public HashMap<T1, T2> keyValue;
    public HashMap<T2, T1> valueKey;

    public SmartHashMap(){
        this.keyValue = new HashMap<T1, T2>();
        this.valueKey = new HashMap<T2, T1>();
    }

    public void add(T1 key, T2 value){
        this.keyValue.put(key, value);
        this.valueKey.put(value, key);
    }

    public T2 getValue(T1 key){
        return this.keyValue.get(key);
    }

    public T1 getKey(T2 value){
        return this.valueKey.get(value);
    }

}

Penso che questa risposta potrebbe essere migliorata aggiungendo una spiegazione.
Jonathan,

2
-1. L'ho provato Stringcome chiave e valore. Quando chiamo map.add("1", "2"); map.add("1","3");allora posso chiamare map.getKey("2");e recuperare "1", anche se "1"è la chiave per "3".
jlordo,

@Jonathan l'idea alla base di questa classe è quella di mantenere un'altra HashMap con i mapping inversi in modo che oltre a recuperare un valore da una chiave, sia possibile recuperare una chiave da un valore. Le classi T1 e T2 sono un po 'confuse; forse letteralmente chiamali invece Key & Value? Sebbene mi aspetterei la possibilità di ricevere più di un valore o più di una chiave in cambio, a seconda dei dati e di ciò che desideri. Usare con cautela
Chicowitz,

1
@theknightwhosaysni "1" non è la chiave per "2" (più). Questa è anche la risposta alla tua domanda, la chiamata getValue("1")tornerà 3.
jlordo,

Scusa jlordo, mi sono sbagliato sul comportamento standard di Hashmap: hai ragione nel dire che l'aggiunta di un nuovo valore per una chiave dovrebbe sostituire il vecchio valore
Chicowitz,

2

In java8

map.entrySet().stream().filter(entry -> entry.getValue().equals(value))
    .forEach(entry -> System.out.println(entry.getKey()));

2
public static String getKey(Map<String, Integer> mapref, String value) {
    String key = "";
    for (Map.Entry<String, Integer> map : mapref.entrySet()) {
        if (map.getValue().toString().equals(value)) {
            key = map.getKey();
        }
    }
    return key;
}

Mappa <String, Integer> map = new HashMap <String, Integer> (); map.put ("A", 1); map.put ("B", 2); map.put ("C", 3); map.put ("D", 4); // System.out.println (mappa); System.out.println (getKey (map, "4"));
Incredibile India il

1
Cosa succede se più chiavi hanno lo stesso valore?
Cà phê 22en,

Quando passi più chiavi hanno lo stesso valore, otterremo l'ultima chiave come risultato. esempio: A 1, B 1, C 1, D 2 output: se passiamo il valore 1, l'output sarà C
Amazing India

@AmazingIndia Questo non è garantito e dipende completamente dalla specifica implementazione della mappa. HashMap, ad esempio, non garantisce un ordine, quindi non hai idea di quale output verrà restituito qui.
Niels Doucet,

1
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;

public class ValueKeysMap<K, V> extends HashMap <K,V>{
    HashMap<V, Set<K>> ValueKeysMap = new HashMap<V, Set<K>>();

    @Override
    public boolean containsValue(Object value) {
        return ValueKeysMap.containsKey(value);
    }

    @Override
    public V put(K key, V value) {
        if (containsValue(value)) {
            Set<K> keys = ValueKeysMap.get(value);
            keys.add(key);
        } else {
            Set<K> keys = new HashSet<K>();
            keys.add(key);
            ValueKeysMap.put(value, keys);
        }
        return super.put(key, value);
    }

    @Override
    public V remove(Object key) {
        V value = super.remove(key);
        Set<K> keys = ValueKeysMap.get(value);
        keys.remove(key);
        if(keys.size() == 0) {
           ValueKeysMap.remove(value);
        }
        return value;
    }

    public Set<K> getKeys4ThisValue(V value){
        Set<K> keys = ValueKeysMap.get(value);
        return keys;
    }

    public boolean valueContainsThisKey(K key, V value){
        if (containsValue(value)) {
            Set<K> keys = ValueKeysMap.get(value);
            return keys.contains(key);
        }
        return false;
    }

    /*
     * Take care of argument constructor and other api's like putAll
     */
}

1
/**
 * This method gets the Key for the given Value
 * @param paramName
 * @return
 */
private String getKeyForValueFromMap(String paramName) {
    String keyForValue = null;
    if(paramName!=null)) {
        Set<Entry<String,String>> entrySet = myMap().entrySet();
        if(entrySet!=null && entrySet.size>0) {
            for(Entry<String,String> entry : entrySet) {
                if(entry!=null && paramName.equalsIgnoreCase(entry.getValue())) {
                    keyForValue = entry.getKey();
                }
            }
        }
    }
    return keyForValue;
}

1
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

public class M{
public static void main(String[] args) {

        HashMap<String, List<String>> resultHashMap = new HashMap<String, List<String>>();

        Set<String> newKeyList = resultHashMap.keySet();


        for (Iterator<String> iterator = originalHashMap.keySet().iterator(); iterator.hasNext();) {
            String hashKey = (String) iterator.next();

            if (!newKeyList.contains(originalHashMap.get(hashKey))) {
                List<String> loArrayList = new ArrayList<String>();
                loArrayList.add(hashKey);
                resultHashMap.put(originalHashMap.get(hashKey), loArrayList);
            } else {
                List<String> loArrayList = resultHashMap.get(originalHashMap
                        .get(hashKey));
                loArrayList.add(hashKey);
                resultHashMap.put(originalHashMap.get(hashKey), loArrayList);
            }
        }

        System.out.println("Original HashMap : " + originalHashMap);
        System.out.println("Result HashMap : " + resultHashMap);
    }
}

1

Utilizzare un involucro sottile: HMap

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

public class HMap<K, V> {

   private final Map<K, Map<K, V>> map;

   public HMap() {
      map = new HashMap<K, Map<K, V>>();
   }

   public HMap(final int initialCapacity) {
      map = new HashMap<K, Map<K, V>>(initialCapacity);
   }

   public boolean containsKey(final Object key) {
      return map.containsKey(key);
   }

   public V get(final Object key) {
      final Map<K, V> entry = map.get(key);
      if (entry != null)
         return entry.values().iterator().next();
      return null;
   }

   public K getKey(final Object key) {
      final Map<K, V> entry = map.get(key);
      if (entry != null)
         return entry.keySet().iterator().next();
      return null;
   }

   public V put(final K key, final V value) {
      final Map<K, V> entry = map
            .put(key, Collections.singletonMap(key, value));
      if (entry != null)
         return entry.values().iterator().next();
      return null;
   }
}

1

I miei 2 centesimi. È possibile ottenere le chiavi in ​​un array e quindi passare in rassegna l'array. Ciò influirà sulle prestazioni di questo blocco di codice se la mappa è piuttosto grande, dove in te vengono prima ottenute le chiavi in ​​un array che potrebbe richiedere un po 'di tempo e quindi eseguire il loop. Altrimenti per le mappe più piccole dovrebbe essere ok.

String[] keys =  yourMap.keySet().toArray(new String[0]);

for(int i = 0 ; i < keys.length ; i++){
    //This is your key    
    String key = keys[i];

    //This is your value
    yourMap.get(key)            
}

E perché qualcuno dovrebbe usare questo approccio? Come hai già detto, le prestazioni sarebbero peggiori rispetto ad altri approcci.
Tom,

1

Penso che keySet () possa essere utile per trovare la mappatura delle chiavi sul valore e avere uno stile di codifica migliore di entrySet () .

Ex:

Supponiamo di avere una mappa HashMap , ArrayList res , un valore in cui si desidera trovare tutta la mappatura delle chiavi , quindi memorizzare le chiavi nella res .

Puoi scrivere il codice qui sotto:

    for (int key : map.keySet()) {
        if (map.get(key) == value) {
            res.add(key);
        }
    }

anziché utilizzare entrySet () di seguito:

    for (Map.Entry s : map.entrySet()) {
        if ((int)s.getValue() == value) {
            res.add((int)s.getKey());
        }
    }

Spero che sia d'aiuto :)


map.get(key) == valuenon è una buona idea quando si controlla l'uguaglianza degli oggetti, in quanto si confrontano i riferimenti. L'uguaglianza degli oggetti dovrebbe sempre usare il loro.equals()
frododot il

1

Anche se questo non risponde direttamente alla domanda, è correlato.

In questo modo non è necessario continuare a creare / iterare. Basta creare una mappa inversa una volta e ottenere ciò di cui hai bisogno.

/**
 * Both key and value types must define equals() and hashCode() for this to work.
 * This takes into account that all keys are unique but all values may not be.
 *
 * @param map
 * @param <K>
 * @param <V>
 * @return
 */
public static <K, V> Map<V, List<K>> reverseMap(Map<K,V> map) {
    if(map == null) return null;

    Map<V, List<K>> reverseMap = new ArrayMap<>();

    for(Map.Entry<K,V> entry : map.entrySet()) {
        appendValueToMapList(reverseMap, entry.getValue(), entry.getKey());
    }

    return reverseMap;
}


/**
 * Takes into account that the list may already have values.
 * 
 * @param map
 * @param key
 * @param value
 * @param <K>
 * @param <V>
 * @return
 */
public static <K, V> Map<K, List<V>> appendValueToMapList(Map<K, List<V>> map, K key, V value) {
    if(map == null || key == null || value == null) return map;

    List<V> list = map.get(key);

    if(list == null) {
        List<V> newList = new ArrayList<>();
        newList.add(value);
        map.put(key, newList);
    }
    else {
        list.add(value);
    }

    return map;
}

0

È importante notare che da questa domanda, Apache Collections supporta BidiMaps generiche . Quindi alcune delle risposte più votate non sono più accurate su questo punto.

Per una BidiMap serializzata che supporta anche valori duplicati (scenario da 1 a molti), prendi in considerazione MapDB.org .


0
  1. Se vuoi ottenere la chiave dal valore, è meglio usare bidimap (mappe bidirezionali), puoi ottenere la chiave dal valore nel tempo O (1).

    Ma lo svantaggio è che puoi usare solo keyset e valoriet unici.

  2. C'è una struttura di dati chiamata Tabella in Java, che non è altro che una mappa di mappe simili

    Tabella <A, B, C> == mappa <A, mappa <B, C>>

    Qui puoi ottenere map<B,C>eseguendo una query T.row(a);e puoi anche ottenere una map<A,C>queryT.column(b);

Nel tuo caso speciale, inserisci C come costante.

Quindi, come <a1, b1, 1> <a2, b2, 1>, ...

Quindi, se trovi tramite T.row (a1) ---> restituisce la mappa di -> ottieni keyset questa mappa restituita.

Se è necessario trovare il valore chiave, T.column (b2) -> restituisce la mappa di -> ottiene il keyset della mappa restituita.

Vantaggi rispetto al caso precedente:

  1. Può usare più valori.
  2. Più efficiente quando si utilizzano set di dati di grandi dimensioni.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.