Java の flatMap
- 
          
            Java の flatMap関数
- 
          
            Java で flatMap()メソッドを使用する方法
- 
          
            Java の flatMapから重複を削除
- 
          
            Java で flatMap要素をフィルタリングする
- 
          
            flatMapとプリミティブ型
- まとめ
 
このチュートリアルでは、flatMap と Java での使用方法を紹介します。
flatMap は、いくつかの機能タスクを実行した後に新しいストリームを取得するために使用される Java ストリームの操作/関数です。ここでは、flatMap() 操作について説明します。
この操作は、map() 操作の拡張です。この関数は各ストリーム要素に適用され、新しい値のストリームを生成します。
これらの新しいストリームで生成された要素は、最近作成されたストリームにコピーされます。このストリームは、メソッドの戻り値として機能します。
Java の flatMap 関数
flatMap() 関数のシグネチャは次のとおりです。
<R> Stream<R> flatMap(Function<? super T,? extends Stream<? extends R>> mapper)
flatMap は中間操作です。中間操作は遅延操作であり、Stream インスタンスで呼び出され、処理が終了すると、Stream インスタンスを返します。
flatMap() 操作は、map() と flat() 操作の組み合わせです。これは、flatMap() 操作が最初に map() 操作を適用し、次に結果をフラット化することを意味します。
このメソッドは、着信 Stream の各要素に適用される関数であるマッパーを使用します。
Java でのフラット化
まず、平坦化とは何かを理解しましょう。リストをフラット化すると、2つ以上のレベルリストが 1つのレベルリストに変換されます。
2つの 2 レベルのリストの例は次のとおりです。
[[ "I" ], [ "Love" ], [ "Delft", "Stack" ]]
平坦化後の上記のリストは、次のように変換されます。
["I", "Love", "Delft", "Stack"]
作成されるリストは単一レベルのリストです。
リストを平坦化する必要性
複数のストリームレベルを処理することは困難で、複雑で、エラーが発生しやすいため、リストをフラット化する必要があります。
Stream.flatMap() 操作を使用して、2つのストリームレベルを 1つのレベルのストリームに変換できます。これは、この記事の後半の例を使用して理解します。
Java で flatMap() メソッドを使用する方法
この例では、最初に stream() メソッドを使用してリストからオブジェクトのストリームを作成しました。各オブジェクトは会社のプログラマーです。
まず、会社の開発者/プログラマーを表すクラスを作成します。
import java.util.HashSet;
import java.util.Set;
class Programmer {
  private String name;
  private Set<String> languages_known;
  public Programmer(String name) {
    this.name = name;
    this.languages_known = new HashSet<>();
  }
  public void addLanguage(String lang) {
    this.languages_known.add(lang);
  }
  public Set<String> getLanguages() {
    return languages_known;
  }
}
次に、オブジェクトを初期化し、会社全体のプログラマーが知っているすべての言語を含むリストのリストを作成します。次に、そのリストをフラット化して、チーム内のすべての言語を把握します。
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
public class SimpleTesting {
  public static void main(String[] args) {
    Programmer raj = new Programmer("Raj");
    raj.addLanguage("Java");
    raj.addLanguage("Dart");
    raj.addLanguage("go");
    raj.addLanguage("groovy");
    Programmer karan = new Programmer("Karan");
    karan.addLanguage("Java");
    karan.addLanguage("Python");
    Programmer chahal = new Programmer("Chahal");
    chahal.addLanguage("Dart");
    chahal.addLanguage("Javascript");
    List<Programmer> team = new ArrayList<>();
    team.add(raj);
    team.add(karan);
    team.add(chahal);
    System.out.println("Programming languages in the team: ");
    List<String> languages = team.stream()
                                 .map(Programmer::getLanguages)
                                 .flatMap(Collection::stream)
                                 .collect(Collectors.toList());
    System.out.println(languages);
  }
}
出力:
Programming languages in the team: 
[Java, groovy, go, Dart, Java, Python, Javascript, Dart]
上記の例では、最初にストリーム API を使用してすべてのプログラマーのストリームを作成しました。その後、map() 関数を使用して、各プログラマーが知っている言語のリストのストリームを作成しました。
Java の flatMap から重複を削除
次に、flatMap() 操作を使用してこのリストをフラット化し、結果のストリームをリストに変換します。生成されたリストに重複する値があることに注意してください。これらを排除するために、duplicate() 操作を使用します。
以下のコードを見てください。
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
public class SimpleTesting {
  public static void main(String[] args) {
    Programmer raj = new Programmer("Raj");
    raj.addLanguage("Java");
    raj.addLanguage("Dart");
    raj.addLanguage("go");
    raj.addLanguage("groovy");
    Programmer karan = new Programmer("Karan");
    karan.addLanguage("Java");
    karan.addLanguage("Python");
    Programmer chahal = new Programmer("Chahal");
    chahal.addLanguage("Dart");
    chahal.addLanguage("Javascript");
    List<Programmer> team = new ArrayList<>();
    team.add(raj);
    team.add(karan);
    team.add(chahal);
    System.out.println("Programming languages in the team: ");
    List<String> languages = team.stream()
                                 .map(Programmer::getLanguages)
                                 .flatMap(Collection::stream)
                                 .distinct()
                                 .collect(Collectors.toList());
    System.out.println(languages);
  }
}
出力:
Programming languages in the team: 
[Java, groovy, go, Dart, Python, Javascript]
Java で flatMap 要素をフィルタリングする
Dart を除くすべての言語を取得したい場合は、flatMap() で filter() 関数を使用できます。以下のコードを見てください。
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
public class SimpleTesting {
  public static void main(String[] args) {
    Programmer raj = new Programmer("Raj");
    raj.addLanguage("Java");
    raj.addLanguage("Dart");
    raj.addLanguage("go");
    raj.addLanguage("groovy");
    Programmer karan = new Programmer("Karan");
    karan.addLanguage("Java");
    karan.addLanguage("Python");
    Programmer chahal = new Programmer("Chahal");
    chahal.addLanguage("Dart");
    chahal.addLanguage("Javascript");
    List<Programmer> team = new ArrayList<>();
    team.add(raj);
    team.add(karan);
    team.add(chahal);
    System.out.println("Programming languages in the team: ");
    List<String> languages = team.stream()
                                 .map(Programmer::getLanguages)
                                 .flatMap(Collection::stream)
                                 .distinct()
                                 .filter(x -> !x.equals("Dart"))
                                 .collect(Collectors.toList());
    System.out.println(languages);
  }
}
出力:
Programming languages in the team:
[Java, groovy, go, Python, Javascript]
flatMap とプリミティブ型
Java Stream API は、int、float、long からプリミティブ型のストリームをフラット化するなどのプリミティブデータ型に対して、flatMapto{primitive type} のような個別の操作も提供します。
import java.util.Arrays;
import java.util.stream.IntStream;
import java.util.stream.Stream;
public class SimpleTesting {
  public static void main(String[] args) {
    int[] Je_array = {3, 5, 2, 35, 85, 32, 23, 43, 12};
    Stream<int[]> JE_streamArray = Stream.of(Je_array);
    IntStream JE_intStream = JE_streamArray.flatMapToInt(x -> Arrays.stream(x));
    JE_intStream.forEach(x -> System.out.println(x));
  }
}
出力:
3
5
2
35
85
32
23
43
12
まとめ
flatMap() 操作とそれが必要な理由について説明しました。また、Java Stream API がプリミティブデータ型に対して個別の flatMap() 操作を提供する方法についても説明しました。
通常の flatMap() 操作は、プリミティブデータ型にも適用できることに注意してください。