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()
操作は、プリミティブデータ型にも適用できることに注意してください。