2010-12-14 13 views
12

Ya sé cómo hacerlo de la manera difícil y lo he puesto en funcionamiento, iterando sobre las entradas e intercambiando "manualmente". Pero me pregunto si, al igual que muchas tareas, esta se puede resolver de una manera más elegante.Cómo intercambiar claves y valores en un Mapa elegantemente

He leído this post, desafortunadamente no cuentan con soluciones elegantes. Tampoco tengo la posibilidad de usar ningún Guava BiMaps de guayaba ni nada que esté fuera de jdk (la pila de proyectos ya está definida).

que puede suponer que mi mapa es biyectiva, por cierto :)

+3

Adición de una biblioteca de utilidades extra no está realmente cambiando el proyecto "pila" en el que (por ejemplo) Cambio de qué marco de interfaz de usuario que está utilizando sería así.Le insto a que reconsidere su oposición al uso de Guava si es * todo * posible. –

+0

Todo lo que necesita es un solo bucle con una sola línea simple y elegante. EN MI HUMILDE OPINIÓN. Java no es un lenguaje funcional. –

+0

gracias a todos, con todas esas respuestas concisas y superpuestas uno realmente tiene dificultades para elegir cuál aceptar. Supongo que iré con Aaron Digulla por proporcionar una solución alternativa. – kostja

Respuesta

8

El tiempo de ejecución de la API/Java estándar no ofrece un mapa bidireccional, por lo que la única solución es iterar sobre todas las entradas y cambiar manualmente.

Lo que puede hacer es crear una clase contenedora que contenga dos mapas y que tenga un doble put() internamente para que tenga dos vistas rápidas en los datos.

[EDIT] Además, gracias al código abierto, que no tiene que incluir una biblioteca de terceros, puede simplemente copiar las clases que necesita en su propio proyecto.

3

mapas no son como listas, que pueden revertirse mediante el canje de cabeza con cola.

objetos en mapas tienen una posición calculada, y utilizando el valor como clave y la clave como el valor se Requiere para volver a calcular el lugar de almacenamiento, essentialy la construcción de otro mapa. No hay una manera elegante.

Existen, sin embargo, mapas bidireccionales. Esos pueden adaptarse a sus necesidades. Volvería a considerar el uso de bibliotecas de terceros.

2

Hay algunos trabajos que se pueden simplificar hasta cierto punto y no más. ¡Este debe ser uno de ellos!

Si desea hacer el trabajo utilizando las API de Java, entonces la fuerza bruta es el camino a seguir, será rápido (a menos que la colección sea enorme) y será una pieza obvia de código.

20

Si no tiene la opción de utilizar una biblioteca de terceros, que no considere el siguiente código tan feo (aunque algunos lenguajes de programación tienen formas elegantes de hacerlo):

//map must be a bijection in order for this to work properly 
public static <K,V> HashMap<V,K> reverse(Map<K,V> map) { 
    HashMap<V,K> rev = new HashMap<V, K>(); 
    for(Map.Entry<K,V> entry : map.entrySet()) 
     rev.put(entry.getValue(), entry.getKey()); 
    return rev; 
} 
+0

gracias, este me recuerda mi propio código :) – kostja

14
Map<String, Integer> map = new HashMap<>(); 
Map<Integer, String> swapped = map.entrySet().stream().collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey)); 
+0

solución increíble. – chandresh

0

como una sugerencia para responder https://stackoverflow.com/a/42091477/8594421

Esto sólo funciona, si el mapa no es un HashMap y no contiene valores duplicados.

Map<String,String> newMap = oldMap.entrySet().stream().collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey)); 

se emite una excepción

java.lang.IllegalStateException: una llave duplicada

si hay valores más de una vez.

La solución:

HashMap<String,String> newMap = new HashMap<>(); 

for(Map.Entry<String,String> entry : oldMap.entrySet()) 
     newMap.put(entry.getValue(), entry.getKey()); 

// Add inverse to old one 
oldMap.putAll(newMap); 
Cuestiones relacionadas