Java Hashmap: ¿Cómo obtener la clave del valor?
Si tengo el valor "foo"
y un HashMap<String> ftw
para 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?
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);
Si elige utilizar la biblioteca Commons Collections en lugar del marco estándar de Java Collections, puede lograrlo con facilidad.
La BidiMap
interfaz 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 BidiMap
y OrderedBidiMap
las SortedBidiMap
interfaces que ahora admiten genéricos de Java .
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.
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)