
こんにちは。大城です。
本ブログでは、Java SE 8で追加されたStream APIについて、初心者向けに解説していきます。
前回のブログでは、絞り込みや要素の変換などを行う中間処理filterとmapについて紹介しました。中間処理2回目の今回は、flatMapとdistinctについて紹介していきます。
環境
- OS
- Windows10
- Java
- Java8
多重リストを纏めるときに使えるflatMap
前回紹介したmapメソッドと同様に、要素の変換を行うメソッドですが、変換後の型としてStreamを指定します。
例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
public class Main { public static void main(String[] args) { List<List<String>> list = new ArrayList<>(Arrays.asList( Arrays.asList("Tokyo", "Chiba"), Arrays.asList("Saitama", "Kanagawa", "Gunma"), Arrays.asList("Tochigi", "Ibaraki", "Yamanashi"))); System.out.println("------元のlistの内容------"); list.stream() .forEach(l -> System.out.println(l)); System.out.println(""); System.out.println("------flatMapにより纏めた結果------"); list.stream() .flatMap(l -> l.stream()) .forEach(e -> System.out.println(e)); } } |
実行結果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
------元のlistの内容------ [Tokyo, Chiba] [Saitama, Kanagawa, Gunma] [Tochigi, Ibaraki, Yamanashi] ------flatMapにより纏めた結果------ Tokyo Chiba Saitama Kanagawa Gunma Tochigi Ibaraki Yamanashi |
flatMapで纏めた結果、もともと二重のリストの構造をとっていたlistの内容が纏められていることがわかります。
15行目のラムダ式で、StringのListのlを、そのままStreamに変換しています。flatMapでは、mapと違いStreamに変換するように指定します。
mapでは変換後の要素をすべて集めたStreamを返しますが、flatMapではStreamに変換後に全てをつなげたStreamを返り値として返します。
少し複雑な例もご紹介します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
class Prefecture { private String name; private List<String> cities; public Prefecture(String name, List<String> cities) { this.name = name; this.cities = cities; } public String getName() { return name; } public void setName(String name) { this.name = name; } public List<String> getCities() { return cities; } public void setCities(List<String> cities) { this.cities = cities; } } public class Main2 { public static void main(String[] args) { List<Prefecture> prefectureList = new ArrayList<>(Arrays.asList( new Prefecture("Tokyo", Arrays.asList("chiyoda-ku", "chuo-ku", "minato-ku", "sinjuku-ku")), new Prefecture("Chiba", Arrays.asList("chiba-shi", "choshi-shi", "ichikawa-shi")), new Prefecture("Saitama", Arrays.asList("saitama-shi", "kawagoe-shi", "kumagaya-shi")) )); System.out.println("------mapによりPrefectureをStringのListに変換した結果------"); prefectureList.stream() .map(l -> l.getCities()) .forEach(e -> System.out.println(e)); System.out.println(""); System.out.println("------flatMapでStringのListのStreamを纏めた結果------"); prefectureList.stream() .flatMap(l -> l.getCities().stream()) .forEach(e -> System.out.println(e)); } } |
実行結果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
------mapによりPrefectureをStringのListに変換した結果------ [chiyoda-ku, chuo-ku, minato-ku, sinjuku-ku] [chiba-shi, choshi-shi, ichikawa-shi] [saitama-shi, kawagoe-shi, kumagaya-shi] ------flatMapでStringのListのStreamを纏めた結果------ chiyoda-ku chuo-ku minato-ku sinjuku-ku chiba-shi choshi-shi ichikawa-shi saitama-shi kawagoe-shi kumagaya-shi |
PrefectureクラスのメンバcitiesはStringのListです。
44行目のl.getCities().stream()ではStreamを返すので、flatMapでそれらをすべて纏めたStreamを取得しています。
重複の削除を行うdistinct
続いてdistinctメソッドについて説明します。
例をご覧ください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
public class Main { public static void main(String[] args) { List<String> list = Arrays.asList("Tokyo", "Chiba", "Saitama", "Tokyo", "Kanagawa", "Saitama", "Gunma", "Tokyo"); System.out.println("------重複削除を行う前------"); list.stream() .forEach(e -> System.out.println(e)); System.out.println("------distinctによる重複削除実行結果------"); list.stream() .distinct() .forEach(e -> System.out.println(e)); } } |
実行結果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
------重複削除を行う前------ Tokyo Chiba Saitama Tokyo Kanagawa Saitama Gunma Tokyo ------distinctによる重複削除実行結果------ Tokyo Chiba Saitama Kanagawa Gunma |
重複登録した要素が削除されていることが確認できます。
まとめ
いかがでしたか。
flatMapは少し分かりづらいですが、多重配列を1次元の配列に纏めるのは使いやすい機能なのではないかと思います。いずれのメソッドも役立つ機会は多いと思うのでぜひ使ってみてください。
次回では、ソートなどの中間処理メソッドについて解説していこうと思います。
それでは、また。
《関連記事》
- 今更聞けない?Java8の気になる機能3選
- 【Java Stream API 超入門】filterメソッドを使って、条件でコレクション要素をフィルタリングする方法
- 【Java Stream API 超入門】filterメソッドでの絞り込みとmapメソッドによる要素の変換

