Question Comment échanger les clés et les valeurs d'une carte avec élégance


Je sais déjà comment le faire à la dure et l'ai fait fonctionner - itérer sur les entrées et permuter "manuellement". Mais je me demande si, comme beaucoup 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 Guava BiMaps ou quelque chose en dehors du jdk (la pile de projet est déjà définie).

Je peux supposer que ma carte est bijective, btw :)


13
2017-12-14 07:55


origine


Réponses:


Le runtime API / Java standard ne propose pas de mappage bidirectionnel. La seule solution consiste à parcourir toutes les entrées et à les échanger manuellement.

Ce que vous pouvez faire est de créer une classe wrapper qui contient deux cartes et qui fait un double put() en interne, vous avez donc deux vues rapides sur les données.

[EDIT] Aussi, grâce à 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.


8
2017-12-14 08:00



Si vous n'avez pas le choix d'utiliser une bibliothèque tierce, je ne considère pas le code suivant comme moche (même si certains langages de script ont des manières élégantes de le faire):

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

22
2017-12-14 08:07



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

20
2018-02-07 13:46



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

Les objets dans les cartes ont une position calculée, et l'utilisation de la valeur comme clé et de la clé comme valeur est nécessaire pour recalculer le lieu de stockage, en construisant de manière essentielle 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 les bibliothèques tierces.


3
2017-12-14 07:59



Il y a des emplois qui peuvent être simplifiés à un certain point et pas plus. C'est peut-être l'un d'entre eux!

Si vous voulez faire le travail en utilisant des collections Java, seul apis alors brute force est la voie à suivre - ce sera rapide (à moins que la collection soit énorme) et ce sera un morceau de code évident.


2
2017-12-14 08:00



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<String,String> 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<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);

0
2017-10-06 14:37