web-dev-qa-db-fra.com

Map to List après filtrage sur la clé de la carte à l'aide du flux Java8

J'ai un Map<String, List<String>>. Je souhaite transformer cette carte en une liste après filtrage sur la clé de la carte. 

Exemple:

Map<String, List<String>> words = new HashMap<>();
List<String> aList = new ArrayList<>();
aList.add("Apple");
aList.add("Abacus");

List<String> bList = new ArrayList<>();
bList.add("Bus");
bList.add("Blue");
words.put("A", aList);
words.put("B", bList);

Étant donné une clé, disons "B"

Expected Output: ["Bus", "Blue"]

C'est ce que j'essaye:

 List<String> wordsForGivenAlphabet = words.entrySet().stream()
    .filter(x-> x.getKey().equalsIgnoreCase(inputAlphabet))
    .map(x->x.getValue())
    .collect(Collectors.toList());

Je reçois une erreur. Quelqu'un peut-il me fournir un moyen de le faire en Java8?

3
user1639485

Votre sniplet produira un List<List<String>> pas List<String>.

Il vous manque flatMap , qui convertira un flux de listes en un seul flux, donc aplatit votre flux:

List<String> wordsForGivenAlphabet = words.entrySet().stream()
    .filter(x-> x.getKey().equalsIgnoreCase(inputAlphabet))
    .map(Map.Entry::getValue)
    .flatMap(List::stream) 
    .collect(Collectors.toList());

Vous pouvez également ajouter distinct(), si vous ne voulez pas que les valeurs soient répétées.

12
Beri

Federico a raison dans son commentaire, si tout ce que vous voulez, c'est obtenir les valeurs d'une certaine clé (dans une List), pourquoi ne faites-vous pas simplement une get (en supposant que toutes vos clés sont déjà majuscules)? 

 List<String> values = words.get(inputAlphabet.toUpperCase());

Si, d’un autre côté, il s’agit simplement de comprendre le fonctionnement des opérations de flux, il existe un autre moyen de le faire (via Java-9 Collectors.flatMapping)

List<String> words2 = words.entrySet().stream()
            .collect(Collectors.filtering(x -> x.getKey().equalsIgnoreCase(inputAlphabet),
                    Collectors.flatMapping(x -> x.getValue().stream(), 
                          Collectors.toList())));
3
Eugene

Comme il a été dit précédemment après collect, vous obtiendrez List<List<String>> avec une seule valeur ou une valeur nulle. Vous pouvez utiliser findFirst au lieu de collect, il vous retournera Optional<List<String>>.

0
Vitalii Muzalevskyi