web-dev-qa-db-fra.com

Inverser les clés et les valeurs HashMap en Java

C'est une question simple, J'ai un simple HashMap dont je veux inverser les clés et les valeurs.

HashMap<Character, String> myHashMap = new HashMap<Character, String>();
myHashMap.put('a', "test one");
myHashMap.put('b', "test two");

et je veux créer un nouveau HashMap dans lequel je mets les contraires.

HashMap<String, Character> reversedHashMap = new HashMap<String, Character>();
e.g. Keys "test one" & "test two" and values 'a' & 'b'.
48
Ken

Ils sont tous uniques, oui

Si vous êtes certain que vos valeurs sont uniques, vous pouvez parcourir les entrées de votre ancienne carte.

Map<String, Character> myNewHashMap = new HashMap<>();
for(Map.Entry<Character, String> entry : myHashMap.entrySet()){
    myNewHashMap.put(entry.getValue(), entry.getKey());
}

Vous pouvez également utiliser une carte bidirectionnelle comme Guava fournit et utiliser la méthode inverse() :

BiMap<Character, String> myBiMap = HashBiMap.create();
myBiMap.put('a', "test one");
myBiMap.put('b', "test two");

BiMap<String, Character> myBiMapInversed = myBiMap.inverse();

Comme Java-8 est sorti, vous pouvez aussi le faire de cette façon:

Map<String, Integer> map = new HashMap<>();
map.put("a",1);
map.put("b",2);

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

Enfin, j'ai ajouté ma contribution à la bibliothèque proton pack library , qui contient des méthodes utilitaires pour l'API Stream. Avec ça tu pourrais le faire comme ça:

Map<Character, String> mapInversed = MapStream.of(map).inverseMapping().collect();
98
Alexis C.

La bibliothèque de collections Apache commons fournit une méthode utilitaire pour inverser la carte. Vous pouvez l'utiliser si vous êtes sûr que les valeurs de myHashMap sont uniques.

org.Apache.commons.collections.MapUtils.invertMap(Java.util.Map map)

Exemple de code

HashMap<String, Character> reversedHashMap = MapUtils.invertMap(myHashMap) 
18
Riju Thomas

Si les valeurs ne sont pas uniques, le moyen sûr d'inverser la carte consiste à utiliser la fonction groupingBy de Java 8.

Map<String, Integer> map = new HashMap<>();
map.put("a",1);
map.put("b",2);

Map<Integer, List<String>> mapInversed = 
map.entrySet()
   .stream()
   .collect(Collectors.groupingBy(Map.Entry::getValue, Collectors.mapping(Map.Entry::getKey, Collectors.toList())))
5
mob

J'ai écrit une boucle plus simple qui fonctionne aussi (notez que toutes mes valeurs sont uniques):

HashMap<Character, String> myHashMap = new HashMap<Character, String>();
HashMap<String, Character> reversedHashMap = new HashMap<String, Character>();

for (char i : myHashMap.keySet()) {
    reversedHashMap.put(myHashMap.get(i), i);
}
3
Ken

Pour répondre à votre question sur la manière de procéder, vous pouvez obtenir le entrySet de votre carte, puis l'insérer dans la nouvelle carte en utilisant getValue as key et getKey as value

Mais rappelez-vous que les clés dans/ Map sont uniques, ce qui signifie que si vous avez une valeur avec deux clés différentes dans votre carte d'origine, seule la deuxième clé (dans l'ordre des itérations) sera conservée comme valeur dans la nouvelle carte.

2
A4L

Parcourez la liste des clés et des valeurs, puis ajoutez-les.

HashMap<String, Character> reversedHashMap = new HashMap<String, Character>();
for (String key : myHashMap.keySet()){
    reversedHashMap.put(myHashMap.get(key), key);
}
2
hichris123
private <A, B> Map<B, A> invertMap(Map<A, B> map) {
    Map<B, A> reverseMap = new HashMap<>();
    for (Map.Entry<A, B> entry : map.entrySet()) {
        reverseMap.put(entry.getValue(), entry.getKey());
    }
    return reverseMap;
}

Il est important de se rappeler que put remplace la valeur lorsqu'elle est appelée avec la même clé. Donc, si votre carte a deux clés avec la même valeur, une seule d'entre elles existera dans la carte inversée.

1
Mark Hetherington

Testé avec l'extrait de code ci-dessous, testé avec MapUtils et la fonctionnalité Java8 Stream. Cela a fonctionné avec les deux cas.

public static void main(String[] args) {
    Map<String, String> test = new HashMap<String, String>();
    test.put("a", "1");
    test.put("d", "1");
    test.put("b", "2");
    test.put("c", "3");
    test.put("d", "4");
    test.put("d", "41");

    System.out.println(test);

    Map<String, String> test1 = MapUtils.invertMap(test);

    System.out.println(test1);

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

    System.out.println(mapInversed);
}

Output:
{a=1, b=2, c=3, d=41}
{1=a, 2=b, 3=c, 41=d}
{1=a, 2=b, 3=c, 41=d}
0
Deepak Arora