Java Hashmap: ¿Cómo obtener la clave del valor?

Resuelto Nick Heiner asked hace 15 años • 40 respuestas

Si tengo el valor "foo"y un HashMap<String> ftwpara el cual ftw.containsValue("foo")regresa true, ¿cómo puedo obtener la clave correspondiente? ¿Tengo que recorrer el mapa hash? ¿Cuál es la mejor manera de hacer eso?

Nick Heiner avatar Sep 06 '09 00:09 Nick Heiner
Aceptado

Si su estructura de datos tiene un mapeo de muchos a uno entre claves y valores, debe iterar sobre las entradas y seleccionar todas las claves adecuadas:

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;
}

En caso de una relación uno a uno , puede devolver la primera clave coincidente:

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;
}

En 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());
}

Además, para los usuarios de Guava, BiMap puede resultar útil. Por ejemplo:

BiMap<Token, Character> tokenToChar = 
    ImmutableBiMap.of(Token.LEFT_BRACKET, '[', Token.LEFT_PARENTHESIS, '(');
Token token = tokenToChar.inverse().get('(');
Character c = tokenToChar.get(token);
Vitalii Fedorenko avatar May 25 '2010 11:05 Vitalii Fedorenko

Si elige utilizar la biblioteca Commons Collections en lugar del marco estándar de Java Collections, puede lograrlo con facilidad.

La BidiMapinterfaz de la biblioteca de Colecciones es un mapa bidireccional, que le permite asignar una clave a un valor (como los mapas normales) y también asignar un valor a una clave, lo que le permite realizar búsquedas en ambas direcciones. El método admite la obtención de una clave para un valor getKey().

Sin embargo, hay una advertencia: los mapas bidi no pueden tener múltiples valores asignados a claves y, por lo tanto, a menos que su conjunto de datos tenga asignaciones 1:1 entre claves y valores, no puede usar mapas bidi.


Si desea confiar en la API de colecciones de Java, deberá garantizar la relación 1:1 entre claves y valores al momento de insertar el valor en el mapa. Esto es más fácil dicho que hecho.

Una vez que pueda asegurarse de eso, utilice el entrySet()método para obtener el conjunto de entradas (asignaciones) en el Mapa. Una vez que haya obtenido el conjunto cuyo tipo es Map.Entry, repita las entradas, compare el valor almacenado con el esperado y obtenga la clave correspondiente .


Se puede encontrar soporte para mapas bidi con genéricos en Google Guava y las bibliotecas Commons-Collections refactorizadas (esta última no es un proyecto de Apache). Gracias a Esko por señalar la falta de soporte genérico en Apache Commons Collections. El uso de colecciones con genéricos hace que el código sea más fácil de mantener.


Desde la versión 4.0, la biblioteca oficial Apache Commons Collections™ admite genéricos .

Consulte la página de resumen del paquete " org.apache.commons.collections4.bidimap " para obtener la lista de implementaciones disponibles BidiMapy OrderedBidiMaplas SortedBidiMapinterfaces que ahora admiten genéricos de Java .

Vineet Reynolds avatar Sep 05 '2009 17:09 Vineet Reynolds
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());
            }
        }
    }
}

Alguna información adicional... Puede que te resulte útil

Es posible que el método anterior no sea bueno si su mapa hash es realmente grande. Si su mapa hash contiene una asignación de clave única a valor único, puede mantener un mapa hash más que contenga la asignación de valor a clave.

Es decir, debes mantener dos mapas hash.

1. Key to value

2. Value to key 

En ese caso, puede utilizar un segundo mapa hash para obtener la clave.

Fathah Rehman P avatar Oct 12 '2011 08:10 Fathah Rehman P

Puede insertar tanto el par clave-valor como su inverso en la estructura de su mapa.

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

El uso de map.get("theValue") devolverá "theKey".

Es una forma rápida y sucia de crear mapas constantes, que solo funcionarán para unos pocos conjuntos de datos seleccionados:

  • Contiene sólo 1 a 1 pares
  • El conjunto de valores está separado del conjunto de claves (1->2, 2->3 lo rompe)
Chicowitz avatar Nov 19 '2013 17:11 Chicowitz