Comment échanger des clés et des valeurs dans une carte avec élégance

Je sais déjà comment le faire à la dure et le faire fonctionner – itérer sur les entrées et permuter “manuellement”. Mais je me demande si, comme tant de tâches, celle-ci peut être résolue de manière plus élégante.

J’ai lu ce post , malheureusement, il ne propose pas de solutions élégantes. Je n’ai pas non plus la possibilité d’utiliser des BiMaps Guava fantaisistes ou autres éléments extérieurs au jdk (la stack de projet est déjà définie)

Je peux supposer que ma carte est bijective, d’ailleurs 🙂

Le moteur d’exécution standard d’API / Java n’offrant pas de carte bidirectionnelle, la seule solution consiste à effectuer une itération sur toutes les entrées et à les échanger manuellement.

Ce que vous pouvez faire est de créer une classe wrapper qui contient deux mappes et qui effectue un double put() interne afin que vous ayez rapidement deux vues sur les données.

[EDIT] De plus, grâce à l’open source, vous n’avez pas besoin d’inclure une bibliothèque tierce, vous pouvez simplement copier les classes dont vous avez besoin dans votre propre projet.

Si vous n’avez pas le choix d’utiliser une bibliothèque tierce, je ne considère pas le code suivant comme si laid (bien que certains langages de script disposent de manières élégantes de le faire):

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

Les cartes ne sont pas comme des listes, qui peuvent être inversées en échangeant la tête avec la queue.

Les objects dans les cartes ont une position calculée, et en utilisant la valeur comme clé et la clé comme valeur, il serait nécessaire de recalculer le lieu de stockage, essentiellement en construisant une autre carte. Il n’y a pas de manière élégante.

Il existe cependant des cartes bidirectionnelles. Ceux-ci peuvent convenir à vos besoins. Je reconsidérerais l’utilisation de bibliothèques tierces.

Certains travaux peuvent être simplifiés jusqu’à un certain point, sans plus. C’est peut-être l’un d’entre eux!

Si vous voulez faire le travail en utilisant des collections Java seulement, alors la force brute est la voie à suivre – ce sera rapide (sauf si la collection est énorme) et ce sera un morceau de code évident.

Comme un indice pour répondre à https://stackoverflow.com/a/42091477/8594421

Cela ne fonctionne que si la carte n’est pas un HashMap et ne contient pas de valeurs en double.

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

jette une exception

java.lang.IllegalStateException: clé en double

s’il y a des valeurs plus d’une fois.

La solution:

 HashMap newMap = new HashMap<>(); for(Map.Entry entry : oldMap.entrySet()) newMap.put(entry.getValue(), entry.getKey()); // Add inverse to old one oldMap.putAll(newMap); 

Si vous aviez access à apache commons-collections, vous auriez pu utiliser MapUtils.invertMap .

Remarque: Le comportement en cas de valeurs dupliquées n’est pas défini.

(En réponse à cela, il s’agit du premier résultat de Google pour “java invert map”).