web-dev-qa-db-ja.com

Java8ストリームを使用してマップのキーでフィルタリングした後、リストにマップ

Map<String, List<String>>。マップのキーでフィルタリングした後、このマップをリストに変換したいと思います。

例:

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);

キーを与えて、「B」と言います

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

これは私が試していることです:

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

エラーが発生します。誰かがJava8でそれを行う方法を私に提供できますか?

5
user1639485

あなたのスニペットは_List<List<String>>_ではなく_List<String>_を生成します。

リストのストリームを単一のストリームに変換する flatMap がないため、基本的にストリームをフラット化します。

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

値を繰り返したくない場合は、distinct()を追加することもできます。

12
Beri

Federicoは彼のコメントのとおりです。もし特定のキー(List内)の値を取得したいだけなら、単にget(すべてのキーがすでに大文字))?

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

一方、これがストリーム操作の仕組みを理解するだけの場合は、それを行うもう1つの方法があります(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

以前にcollectの後で説明したように、値が1つまたはゼロのList<List<String>>を取得します。 findFirstの代わりにcollectを使用すると、Optional<List<String>>が返されます。

0