map()とflatMap()の違い
1. 概要
map()および flatMap() APIは、関数型言語に由来します。 Java 8では、オプション、ストリームおよび CompleteableFuture にあります(ただし、名前は少し異なります)。
Streams はオブジェクトのシーケンスを表しますが、オプションは存在または不在の値を表すクラスです。 他の集約操作の中には、 map()メソッドと flatMap()メソッドがあります。
両方が同じリターンタイプを持っているという事実にもかかわらず、それらはかなり異なります。 ストリームとオプションの例をいくつか分析して、これらの違いを説明しましょう。
2. オプションのマップとフラットマップ
map()メソッドはオプションでうまく機能します—関数が必要な正確な型を返す場合:
Optional<String> s = Optional.of("test");
assertEquals(Optional.of("TEST"), s.map(String::toUpperCase));
ただし、より複雑なケースでは、オプションも返す関数が与えられる場合があります。 このような場合、 map()を使用すると、 map()実装が内部で追加のラッピングを行うため、ネストされた構造になります。
この状況をよりよく理解するために、別の例を見てみましょう。
assertEquals(Optional.of(Optional.of("STRING")),
Optional
.of("string")
.map(s -> Optional.of("STRING")));
ご覧のとおり、ネストされた構造になりますオプション
それがまさにflatMap()が私たちに役立つことです。
assertEquals(Optional.of("STRING"), Optional
.of("string")
.flatMap(s -> Optional.of("STRING")));
3. ストリームのマップとフラットマップ
どちらの方法も、オプションで同様に機能します。
The 地図() メソッドは、基になるシーケンスをストリームインスタンス、一方、 flatMap() メソッドはネストを回避することができますストリーム
ここで、 map()は、 toUpperCase()メソッドを入力Streamの要素に適用した結果で構成されるStreamを生成します。 :
List<String> myList = Stream.of("a", "b")
.map(String::toUpperCase)
.collect(Collectors.toList());
assertEquals(asList("A", "B"), myList);
map()は、このような単純なケースで非常にうまく機能します。 しかし、入力としてのリストのリストなど、もっと複雑なものがある場合はどうでしょうか。
それがどのように機能するか見てみましょう:
List<List<String>> list = Arrays.asList(
Arrays.asList("a"),
Arrays.asList("b"));
System.out.println(list);
このスニペットは、リスト [[a]、[b]]のリストを出力します。
次に、 flatMap()を使用しましょう。
System.out.println(list
.stream()
.flatMap(Collection::stream)
.collect(Collectors.toList()));
このようなスニペットの結果は、 [a、b]にフラット化されます。
T he flatMap()メソッドは、最初に Stream of StreamsをStreamのにフラット化します。文字列(平坦化の詳細については、この記事を参照してください)。 その後は、 map()メソッドと同様に機能します。
4. 結論
Java 8は、関数型言語で元々使用されていた map()および flatMap()メソッドを使用する機会を提供します。
StreamsおよびOptionalsでそれらを呼び出すことができます。 これらのメソッドは、提供されているマッピング関数を適用することにより、マップされたオブジェクトを取得するのに役立ちます。
いつものように、この記事の例はGitHubでから入手できます。