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

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

 

1. introduction

In this quick tutorial, we’re going to demonstrate three different approaches for retrieving the key from a map for a given value. Nous discuterons également des avantages et des inconvénients des différentes solutions.

Pour en savoir plus sur l'interfaceMap, vous pouvez consulterthis article.

2. Une approche itérative

L'interfaceMap deJava Collections offre une méthode appeléeentrySet(). Il renvoie toutes les entrées ou paires clé-valeur de la carte dans unSet.

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 est possible que plusieurs clés pointent vers la même valeur.

Dans ce cas, si une valeur correspondante est trouvée, nous ajoutons la clé à unSet et continuons la boucle. Au final, nous retournons lesSet 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,it compares all the entries even if all matches are found after a few iterations.

3. Une approche fonctionnelle

With the introduction of Lambda Expressions in Java 8, we can do it in a more flexible and readable way. Nous convertissons l'ensemble d'entrées en unStream et fournissons un lambda pour filtrer uniquement les entrées avec la valeur donnée.

Ensuite, nous utilisons la méthode map pour renvoyer unStream 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);
}

The advantage of returning a stream is that it can cater to a wide range of client needs. 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 utilesif we need to call the functions very frequently for a particular map. Il va itérer inutilement le jeu de ses clés encore et encore.

Dans ce scénario,maintaining another map of value to the keys would make more sense as it will take constant time to retrieve the key for a value.

La bibliothèqueCommons Collections deApache fournit un telMap bidirectionnel appeléBidiMap. Il a une méthode nomméegetKey() 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 imposes a 1:1 relationship between its keys and values. Si nous essayons de mettre une paire clé-valeur pour laquelle la valeur existe déjà dans lesMap,, cela supprime l'ancienne entrée. En d'autres termes, il met à jour la clé par rapport à la valeur.

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

Plus de détails sur la façon d'utiliser unBidiMap sont dansthis tutorial.

5. Utiliser Google Guava

We may use another bi-directional Map called BiMap found in Guava developed by Google. Cette classe fournit une méthode nomméeinverse() pour obtenir la clé de valeurMap ou l'inverseMap 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");

CommeBidiMap,BiMap also doesn’t allow multiple keys referring to the same value. Si nous essayons de fairesuch an attempt, it jette unjava.lang.IllegalArgumentException.

Inutile de dire queBiMap utilise également une quantité importante de mémoire car il doit stocker la carte inverse à l'intérieur. Si vous souhaitez en savoir plus surBiMap, vous pouvez consulterthis tutorial.

6. Conclusion

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

Le code source complet du didacticiel ci-dessus est disponibleover on GitHub.