連載
» 2014年05月20日 18時00分 UPDATE

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

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

[長谷川智之,株式会社ビーブレイクシステムズ]
「Java 8はラムダ式でここまで変わる」のインデックス

連載目次

 前回の「ラムダ式で本領を発揮する関数型インターフェースとStream APIの基礎知識」では、ラムダ式を使うことで本領を発揮する汎用的な関数型インターフェースとStream APIの概要を見てきました。

 今回は、前回に引き続きStream APIについて見ていき、主なメソッドとその使い方を学んでいきましょう。

Streamの生成

 Stream APIを使うには、Streamのインスタンスを生成しなければいけません。まずは、そのStreamインスタンスを生成する方法を見ていきましょう。

配列やCollectionなどからのStreamの生成

 Streamは配列やCollectionなどから作成可能です。まずは配列やCollectionからStreamのインスタンスを生成する主なメソッドを見てみましょう。下記のものが主なメソッドです。

呼び出し元クラス/インターフェース メソッド 概要
Collection<T> stream() Collectionの要素を元にStreamのインスタンスを生成
Arrays stream(T[] array) 引数のarrayの要素を元にStreamのインスタンスを生成
Stream of(T… values) 引数のvaluesを元にStreamのインスタンスを生成。また引数に配列を渡した場合、その配列の要素でできたStreamインスタンスを生成することも可能
List<String> list = Arrays.asList(
        "list1", "list2", "list3", "list4", "list5"
);
String[] array = {"配列1", "配列2", "配列3", "配列4", "配列5"};
// Streamインスタンスの生成
Stream<String> stream1 = list.stream();
Stream<String> stream2 = Arrays.stream(array);
Stream<String> stream3 = Stream.of("1", "2", "3", "4", "5");
Stream<String> stream4 = Stream.of(array);
// Streamの各要素を標準出力します。
stream1.forEach(e -> System.out.println("stream1:" + e));
stream2.forEach(e -> System.out.println("stream2:" + e));
stream3.forEach(e -> System.out.println("stream3:" + e));
stream4.forEach(e -> System.out.println("stream4:" + e));
サンプル
stream1:list1
stream1:list2
stream1:list3
stream1:list4
stream1:list5
stream2:配列1
stream2:配列2
stream2:配列3
stream2:配列4
stream2:配列5
stream3:1
stream3:2
stream3:3
stream3:4
stream3:5
stream4:配列1
stream4:配列2
stream4:配列3
stream4:配列4
stream4:配列5
実行結果

 ここで注意すべき点は、数値を扱うStreamを生成する際に、指定する型が数値のプリミティブ型なのかラッパークラスなのかによって、返ってくるStreamが変わることです。

 例えばArrays#streamメソッドの場合、引数の配列が数値のプリミティブ型(intなど)だと、それに対応した型のStream(IntStreamなど)を返します。しかし、引数がプリミティブ型のラッパークラス(Integerなど)だとStream<ラッパークラス>を返します。

int[] intArray = {1, 2, 3, 4, 5};
Integer[] integerArray = {1, 2, 3, 4, 5};
IntStream intArrayStream = Arrays.stream(intArray);
Stream<Integer> integerArrayStream = Arrays.stream(integerArray);
サンプル

2つのStreamから1つのStreamの生成するメソッド

 次に、2つのStreamの要素を合わせて1つのStreamを生成するメソッドを見てみましょう。

呼び出し元クラス/インターフェース メソッド 概要
Stream<T> concat(Stream<? extends T> s1, Stream<? extends T> s2) 要素が同じ型、もしくは、親が同じ型を持つs1とs2のStreamを結合し1つのStreamのインスタンスを生成
Stream<String> stream1 = Stream.of("あ", "い", "う", "え", "お");
Stream<String> stream2 = Stream.of("ア", "イ", "ウ", "エ", "オ");
Stream<String> concatStream = Stream.concat(stream1, stream2);
concatStream.forEach(value -> System.out.println(value));
サンプル
あ
い
う
え
お
ア
イ
ウ
エ
オ
実行結果

 また、このconcatメソッドの引数が1つでも並列処理のStreamの場合、戻り値のStreamも並列処理を行うものになります。

Stream<String> stream1 = Stream.of("あ", "い", "う", "え", "お");
Stream<String> stream2 = Stream.of("ア", "イ", "ウ", "エ", "オ");
Stream<String> parallelStream = stream1.parallel();
Stream<String> concatStream = Stream.concat(parallelStream, stream2);
concatStream.forEach(value -> System.out.println(value));
System.out.println("concatStream.isParallel()=" + concatStream.isParallel());
サンプル
イ
ア
エ
い
あ
お
え
ウ
う
オ
concatStream.isParallel()=true
実行結果

並列処理を行うStreamの生成

 前回の連載で説明したようにJava 8では並列処理を行うStreamインスタンスを簡単に生成するためのメソッドが用意されています。並列処理を行うStreamを生成する場合は下記のメソッドが使えます。

呼び出し元クラス/インターフェース メソッド 概要
Collection parallelStream() Collectionを元に並列処理を行うStreamのインスタンスを生成
BaseStream parallel() 呼び出し元のStreamから並列処理を行うStreamを返す

 また、Streamのインスタンスが並列処理を行うものかどうかチェックするにはBaseStream#isParallelメソッドで確認可能です。このメソッドを実行した際にTrueが返れば、並列処理を行うものになります。

 逆に、並列処理から直列処理のStreamを生成する場合はBaseStream# sequentialメソッドで直列処理のStreamを生成可能です。

List<String> list = Arrays.asList(
        "list1", "list2", "list3", "list4", "list5"
);
// 並列処理を行うStreamを生成
Stream<String> parallelStream1 = list.parallelStream();
Stream<String> parallelStream2 = list.stream().parallel();
// 生成されたStreamが並列処理を行うものか確認
System.out.println("parallelStream1.isParallel()=" + parallelStream1.isParallel());
System.out.println("parallelStream2.isParallel()=" + parallelStream2.isParallel());
// 並列処理から直接処理に変換
Stream<String> sequentialStream = parallelStream1.sequential();
System.out.println("sequentialStream.isParallel()=" + sequentialStream.isParallel());
サンプル
parallelStream1.isParallel()=true
parallelStream2.isParallel()=true
sequentialStream.isParallel()=false
実行結果
       1|2|3|4 次のページへ

Copyright© 2017 ITmedia, Inc. All Rights Reserved.

@IT Special

- PR -

TechTargetジャパン

この記事に関連するホワイトペーパー

Focus

- PR -

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。