Obtenga la clave de un valor de un mapa de Java

1. Introducción

En este tutorial rápido, vamos a demostrar tres enfoques diferentes para recuperar la clave de un mapa para un valor dado. También discutiremos los aspectos positivos y negativos de las diversas soluciones.

Para obtener más información sobre la interfaz del mapa , puede consultar este artículo.

2. Un enfoque iterativo

La interfaz Map de Java Collections ofrece un método llamado entrySet () . Devuelve todas las entradas o pares clave-valor del mapa en un conjunto .

La idea es iterar sobre este conjunto de entradas y devolver la clave para la que el valor coincide con el valor proporcionado:

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

Sin embargo, podría existir la posibilidad de que varias claves apunten al mismo valor.

En ese caso, si se encuentra un valor coincidente, agregamos la clave a un conjunto y continuamos el ciclo. Al final, devolvemos el Set que contiene todas las claves deseadas:

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

Aunque esta es una implementación muy sencilla, compara todas las entradas incluso si todas las coincidencias se encuentran después de algunas iteraciones.

3. Un enfoque funcional

Con la introducción de Lambda Expressions en Java 8, podemos hacerlo de una manera más flexible y legible. Convertimos el conjunto de entradas a Stream y proporcionamos una lambda para filtrar solo aquellas entradas con el valor dado.

Luego usamos el método del mapa para devolver una secuencia de las claves de las entradas filtradas:

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

La ventaja de devolver una transmisión es que puede satisfacer una amplia gama de necesidades del cliente. El código de llamada puede requerir solo una clave o todas las claves apuntando al valor proporcionado. Como la evaluación de una secuencia es lenta, el cliente puede controlar el número de iteraciones según sus requisitos.

Además, el cliente puede convertir el flujo a cualquier colección usando un recolector apropiado:

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

4. Uso de colecciones de Apache Commons

Las ideas anteriores no serían muy útiles si necesitamos llamar a las funciones con mucha frecuencia para un mapa en particular . Iterará innecesariamente el conjunto de sus claves una y otra vez.

En este escenario, mantener otro mapa de valor para las claves tendría más sentido, ya que tomará un tiempo constante recuperar la clave para un valor.

La biblioteca Commons Collections de Apache proporciona un mapa bidireccional llamado BidiMap . Tiene un método llamado getKey () para recuperar una clave para un valor dado:

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

Sin embargo, BidiMap impone una relación 1: 1 entre sus claves y valores . Si intentamos poner un par clave-valor para el que el valor ya existe en el mapa, elimina la entrada anterior. En otras palabras, actualiza la clave con el valor.

Además, requiere una mayor cantidad de memoria para mantener el mapa inverso.

En este tutorial encontrará más detalles sobre cómo utilizar un BidiMap .

5. Uso de Google Guava

Podemos utilizar otro mapa bidireccional llamado BiMap que se encuentra en Guava desarrollado por Google. Esta clase proporciona un método llamado inverse () para obtener el mapa de clave de valor o el mapa inverso para obtener la clave en función de un valor dado:

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

Al igual que BidiMap , BiMap tampoco permite varias claves que se refieran al mismo valor . Si intentamos hacer tal intento, arroja una java.lang.IllegalArgumentException .

No hace falta decir que BiMap también utiliza una cantidad significativa de memoria, ya que tiene que almacenar el mapa inverso en su interior. Si está interesado en saber más sobre BiMap , puede consultar este tutorial.

6. Conclusión

En este breve artículo, analizamos algunos métodos para recuperar la clave de un mapa dado el valor. Cada acercamiento tiene sus propios pros y contras. Siempre debemos considerar los casos de uso y elegir el más apropiado en función de la situación.

El código fuente completo para el tutorial anterior está disponible en GitHub.