web-dev-qa-db-fra.com

Java 8 extrait la première clé de la valeur correspondante dans une carte

Supposons que j’ai une carte des paires de prénoms et de nom de famille et que je souhaite trouver le prénom de la première entrée de cette carte portant le nom de famille correspondant à une certaine valeur .. Comment procéder de cette manière avec Java 8?.

Dans mon exemple de test ci-dessous, je propose deux méthodes.

Cependant, le premier (en recherchant le prénom de la première personne portant le nom de famille "Donkey") lancera Java.util.NoSuchElementException: aucune valeur n'est présente, donc ce n'est pas sûr.

Le second fonctionne mais ce n’est pas seulement plus dur à lire mais c’est un peu pas tout à fait fonctionnel.

Je me demandais simplement si quelqu'un ici me suggèrerait un moyen plus clair et plus simple d'y parvenir en utilisant stream() ou forEach() ou les deux.

@Test
public void shouldBeAbleToReturnTheKeyOfTheFirstMatchingValue() throws Exception {
    Map<String, String> names = new LinkedHashMap<>();
    names.put("John", "Doe");
    names.put("Fred", "Flintstone");
    names.put("Jane", "Doe");
    String keyOfTheFirst = names.entrySet().stream().filter(e -> e.getValue().equals("Doe")).findFirst().get().getKey();
    assertEquals("John", keyOfTheFirst);

    try {
        names.entrySet().stream().filter(e -> e.getValue().equals("Donkey")).findFirst().get();
    } catch (NoSuchElementException e){
        // Expected
    }

    Optional<Map.Entry<String, String>> optionalEntry = names.entrySet().stream().filter(e -> e.getValue().equals("Donkey")).findFirst();
    keyOfTheFirst = optionalEntry.isPresent() ? optionalEntry.get().getKey() : null;

    assertNull(keyOfTheFirst);
}

Merci d'avance.

17
Julian

Pour renvoyer une valeur par défaut s'il n'y a pas de correspondance, utilisez Optional#orElse

names.entrySet().stream()
  .filter(e -> e.getValue().equals("Donkey"))
  .map(Map.Entry::getKey)
  .findFirst()
  .orElse(null);
52
Misha

La solution fournie par @Misha est la meilleure si vous ne souhaitez pas utiliser le code tiers. Ma bibliothèque a la méthode de raccourci spéciale ofKeys pour les cas où j'ai découvert que c'était une tâche assez courante:

StreamEx.ofKeys(names, "Donkey"::equals).findFirst().orElse(null);
1
Tagir Valeev

D'un semblable question :

public static <T, E> Set<T> getKeysByValue(Map<T, E> map, E value) {
    return map.entrySet()
              .stream()
              .filter(entry -> Objects.equals(entry.getValue(), value))
              .map(Map.Entry::getKey)
              .collect(Collectors.toSet());
}

Ensuite, vous pouvez sélectionner le premier, si vous le souhaitez. Rappelez-vous que la key est unique, la value ne l’est pas.

Edit: Tout le code (merci @ Peter Lawrey)

package test;

import Java.util.LinkedHashMap;
import Java.util.Map;
import Java.util.Objects;
import Java.util.Optional;

public class Main {

    public static void main(String[] args) {
        Map<String, String> names = new LinkedHashMap<>();
        names.put("John", "Doe");
        names.put("Fred", "Flintstone");
        names.put("Jane", "Doe");

        Optional<String> firstKey = names.entrySet().stream()
                .filter(entry -> Objects.equals(entry.getValue(), "Doe"))
                .map(Map.Entry::getKey).findFirst();

        if (firstKey.isPresent()) {
            System.out.println(firstKey.get());
        }
    }
}
0
Doon

Ci-dessous mon extrait de code pour obtenir la clé de la carte, 

Map<String,String> pageDetails = new HashMap<String,String>();

public String getAssociatedKey(){
pageDetails.entrySet().stream().filter( e -> e.getValue().contains("John").findFirst().get().getKey();
}
0
Pavan T

J'aime le vieux façonné:

static <K, V> K findFirstKeyByValue(Map<K, V> map, String value) {
    for (Entry<K, V> e : map.entrySet())
        if (e.getValue().equals(value))
            return e.getKey();
    return null;
}
0
saka1029