検索
連載

Stream APIの主なメソッドと処理結果のOptionalクラスの使い方Java 8はラムダ式でここまで変わる(4)(2/4 ページ)

本連載では、今までJavaの経験はあっても「ラムダ式は、まだ知らない」という人を対象にラムダ式について解説していきます。今回は、Java 8の新機能Stream APIの使い方について。Streamの生成、中間的な処理を行うメソッド、最終的な処理を行うメソッド、結果として使われるOptionalについてコード例を交えて解説します。

PC用表示 関連情報
Share
Tweet
LINE
Hatena

中間的な処理を行うメソッド

 前回の連載で説明したように、Stream APIでは0個以上の中間的な処理を行うメソッドでStreamの要素を絞り込んだり変換したりして、最終的な処理を行うメソッドで結果を取得します。まずは中間的な処理を行うメソッドを見てみましょう。

要素を絞り込むメソッド

 まずは、Streamが持っている要素から条件で絞るメソッドを見てみましょう。これらのメソッドは条件によって絞り込んだStreamを戻り値として返します。主なものは次のメソッドです。

メソッド 概要
filter(Predicate<? super T> predicate) Predicateで定義したbooleanの判定がtrueの要素のみに絞ったStream<T>を返す
limit(long maxSize) 要素の最初からmaxSizeまでの要素のStreamを返す
distinct() 要素同士をequalsメソッドで比較し重複するものを除いたStreamを返す
Integer[] array = {1,2,3,4,5,1,2,3,4,5}; 
System.out.println("----- filterメソッド -----");
Stream<Integer> stream1 = Arrays.stream(array);
// 要素を偶数のみに絞ります
Stream<Integer> filterStream = stream1.filter(value -> value%2 == 0);
filterStream.forEach(value -> System.out.println("filterStream: " + value));
System.out.println("----- limitメソッド -----");
Stream<Integer> stream2 = Arrays.stream(array);
// 要素を最初から3要素までに絞ります
Stream<Integer> limitStream = stream2.limit(3);
limitStream.forEach(value -> System.out.println("limitStream: " + value));
System.out.println("----- distinctメソッド -----");
Stream<Integer> stream3 = Arrays.stream(array);
// 要素の重複をなくします
Stream<Integer> distinctStream = stream3.distinct();
distinctStream.forEach(value -> System.out.println("distinctStream: " + value));
サンプル
----- filterメソッド -----
filterStream: 2
filterStream: 4
filterStream: 2
filterStream: 4
----- limitメソッド -----
limitStream: 1
limitStream: 2
limitStream: 3
----- distinctメソッド -----
distinctStream: 1
distinctStream: 2
distinctStream: 3
distinctStream: 4
distinctStream: 5
実行結果

 注意すべき点として、この中のlimitメソッドは並列処理のStreamインスタンスの場合でも直列処理のStreamと同様に、要素の最初から引数で指定した数の要素を順番に取得します。

Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5);
Stream<Integer> parallelStream = stream.parallel();
parallelStream.limit(3).forEach(value -> System.out.println(value));
サンプル
1
3
2
実行結果

 この並列処理のStreamでのlimitメソッドを使った場合、Streamが持つ最初の要素から順に取得していくため、並列処理のメリットが生かされず遅くなる可能性があるので注意してください。

Streamの要素から別の要素のStreamを生成するメソッド

 次はStreamの要素から別の要素のStreamを生成するメソッドを見てみましょう。次のメソッドが主なものです。

メソッド 概要
map(Function<? super T, ? extends R> function) functionが引数として受け取ったTからRを返し、そのRを要素として生成されたStream<R>を返す
flatMap(Function<? super T, ? extends Stream<? extends R>> function) functionが引数として受け取ったTから複数のRを生成する場合、それらのRを要素として生成された1つのStream<R>にして返す

 例えば、名前と子どものListを持つ下記のPersonというクラスがあったとします。

public class Person {
    /** 名前 */
    private String name;
    
    /** 子ども */
    private List<String> children = new ArrayList<>();
    public Person(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
    public void addChild(String name) {
        children.add(name);
    }
    public List<String> getChildren() {
        return children;
    }
}

 ここではmapメソッドを使ってこのPersonクラスの名前を要素として持つStreamを作る例と、flatMapメソッドを使ってPersonクラスの各子どもを要素として持つStreamを作る例を次に示します。

Person person1 = new Person("サンプル 太郎");
person1.addChild("サンプル 小太郎");
person1.addChild("サンプル 小次郎");
Person person2 = new Person("デモ 花子");
person2.addChild("デモ 小太郎");
person2.addChild("デモ 小次郎");
List<Person> list = new ArrayList<>();
list.add(person1);
list.add(person2);
// PersonのListから名前のStreamを作成する
Stream<String> mapStream = list.stream().map(person -> person.getName());
mapStream.forEach(name->System.out.println("map: " + name));
// PersonのListから子どもの名前のStreamを作成する
Stream<String> flatMapStream = list.stream().flatMap(person -> person.getChildren().stream());
flatMapStream.forEach(child->System.out.println("flatMap: " + child));
サンプル
map: サンプル 太郎
map: デモ 花子
flatMap: サンプル 小太郎
flatMap: サンプル 小次郎
flatMap: デモ 小太郎
flatMap: デモ 小次郎
実行結果

 またmapメソッドとflatMapメソッドから派生したメソッドの中にはIntStreamのような数値のプリミティブ型の要素のStreamを返すメソッドも用意されています。例えばmapToIntメソッドは、int値の要素でできたIntStreamを返します。

要素を並べ替えるメソッド

 Streamの要素を並べ替えるメソッドには、主に次のものがあります。

メソッド 概要
sorted(Comparator<? super T> comparator) Comparatorで比較し並べ替えたStream<T>を返す
List<String> list = Arrays.asList(new String[]{"あ","い","う","え","お", "あ","い","う","え","お"});
Stream<String> sortedStream = list.stream().sorted((e1,e2) -> e1.compareTo(e2));
sortedStream.forEach(e->System.out.println("sorted: " + e));
サンプル
sorted: あ
sorted: あ
sorted: い
sorted: い
sorted: う
sorted: う
sorted: え
sorted: え
sorted: お
sorted: お
実行結果

Copyright © ITmedia, Inc. All Rights Reserved.

ページトップに戻る