Obtenir la clé d'une valeur à partir d'une carte Java

1. Introduction

Dans ce rapide tutoriel, nous allons démontrer trois approches différentes pour récupérer la clé d'une carte pour une valeur donnée. Nous discuterons également des avantages et des inconvénients des différentes solutions.

Pour en savoir plus sur l' interface de la carte , vous pouvez consulter cet article.

2. Une approche itérative

L' interface Map de Java Collections propose une méthode appelée entrySet () . Il renvoie toutes les entrées ou paires clé-valeur de la carte dans un ensemble .

L'idée est d'itérer sur ce jeu d'entrées et de retourner la clé pour laquelle la valeur correspond à la valeur fournie:

public  K getKey(Map map, V value) { for (Entry entry : map.entrySet()) { if (entry.getValue().equals(value)) { return entry.getKey(); } } return null; }

Cependant, il se peut que plusieurs clés pointent vers la même valeur.

Dans ce cas, si une valeur correspondante est trouvée, nous ajoutons la clé à un Set et continuons la boucle. Au final, nous retournons l' ensemble contenant toutes les clés souhaitées:

public  Set getKeys(Map map, V value) { Set keys = new HashSet(); for (Entry entry : map.entrySet()) { if (entry.getValue().equals(value)) { keys.add(entry.getKey()); } } return keys; }

Bien qu'il s'agisse d'une implémentation très simple, elle compare toutes les entrées même si toutes les correspondances sont trouvées après quelques itérations.

3. Une approche fonctionnelle

Avec l'introduction des expressions Lambda dans Java 8, nous pouvons le faire d'une manière plus flexible et lisible. Nous convertissons l'ensemble d'entrées en Stream et fournissons un lambda pour filtrer uniquement les entrées avec la valeur donnée.

Ensuite, nous utilisons la méthode map pour renvoyer un Stream des clés des entrées filtrées:

public  Stream keys(Map map, V value) { return map .entrySet() .stream() .filter(entry -> value.equals(entry.getValue())) .map(Map.Entry::getKey); }

L'avantage de renvoyer un flux est qu'il peut répondre à un large éventail de besoins des clients. Le code appelant peut nécessiter une seule touche ou toutes les touches pointant vers la valeur fournie. Comme l'évaluation d'un flux est paresseuse, le client peut contrôler le nombre d'itérations en fonction de ses besoins.

De plus, le client peut convertir le flux en n'importe quelle collection à l'aide d'un collecteur approprié:

Stream keyStream1 = keys(capitalCountryMap, "South Africa"); String capital = keyStream1.findFirst().get(); Stream keyStream2 = keys(capitalCountryMap, "South Africa"); Set capitals = keyStream2.collect(Collectors.toSet());

4. Utilisation des collections Apache Commons

Les idées ci-dessus ne seraient pas très utiles si nous devons appeler les fonctions très fréquemment pour une carte particulière . Il répétera inutilement l'ensemble de ses clés encore et encore.

Dans ce scénario, conserver une autre mappe de valeur sur les clés aurait plus de sens car il faudra un temps constant pour récupérer la clé pour une valeur.

La bibliothèque Commons Collections d' Apache fournit une telle carte bidirectionnelle appelée BidiMap . Il a une méthode nommée getKey () pour récupérer une clé pour une valeur donnée:

BidiMap capitalCountryMap = new DualHashBidiMap(); capitalCountryMap.put("Berlin", "Germany"); capitalCountryMap.put("Cape Town", "South Africa"); String capitalOfGermany = capitalCountryMap.getKey("Germany");

Cependant, BidiMap impose une relation 1: 1 entre ses clés et ses valeurs . Si nous essayons de mettre une paire clé-valeur pour laquelle la valeur existe déjà dans la carte, cela supprime l'ancienne entrée. En d'autres termes, il met à jour la clé par rapport à la valeur.

En outre, il nécessite une plus grande quantité de mémoire pour conserver la carte inversée.

Plus de détails sur l'utilisation d'un BidiMap se trouvent dans ce didacticiel.

5. Utilisation de Google Guava

Nous pouvons utiliser une autre carte bidirectionnelle appelée BiMap trouvée dans Guava développée par Google. Cette classe fournit une méthode nommée inverse () pour obtenir la valeur-clé Map ou la carte inverse pour récupérer la clé en fonction d'une valeur donnée:

HashBiMap capitalCountryMap = HashBiMap.create(); capitalCountryMap.put("Berlin", "Germany"); capitalCountryMap.put("Cape Town", "South Africa"); String capitalOfGermany = capitalCountryMap.inverse().get("Germany");

Comme BidiMap , BiMap n'autorise pas non plus plusieurs clés faisant référence à la même valeur . Si nous essayons de faire une telle tentative, cela lance une exception java.lang.IllegalArgumentException .

Inutile de dire que BiMap utilise également une quantité importante de mémoire car il doit stocker la carte inverse à l'intérieur. Si vous souhaitez en savoir plus sur BiMap , vous pouvez consulter ce tutoriel.

6. Conclusion

Dans ce bref article, nous avons discuté de certaines méthodes de récupération de la clé d' une carte en fonction de la valeur. Chaque approche a ses pours et ses contres. Nous devons toujours considérer les cas d'utilisation et choisir le plus approprié en fonction de la situation.

Le code source complet du didacticiel ci-dessus est disponible à l'adresse over sur GitHub.