Stream APIの主なメソッドと処理結果のOptionalクラスの使い方:Java 8はラムダ式でここまで変わる(4)(4/4 ページ)
本連載では、今までJavaの経験はあっても「ラムダ式は、まだ知らない」という人を対象にラムダ式について解説していきます。今回は、Java 8の新機能Stream APIの使い方について。Streamの生成、中間的な処理を行うメソッド、最終的な処理を行うメソッド、結果として使われるOptionalについてコード例を交えて解説します。
要素を判定するメソッド
次はStreamの要素を判定するメソッドを見てみましょう。以下は、主なものです。
戻り値 | メソッド | 概要 |
---|---|---|
boolean | allMatch(Predicate<? super T> predicate) | Streamの全ての要素がpredicateの判定でTrueを返す場合、戻り値としてTrueを返す |
boolean | anyMatch(Predicate<? super T> predicate) | Streamの要素のどれかがpredicateの判定でTrueを返す場合、戻り値としてTrueを返す |
boolean | noneMatch(Predicate<? super T> predicate) | Streamの要素がどれもpredicateの判定でTrueを返さない場合、戻り値としてTrueを返す |
List<BigDecimal> list = new ArrayList<>(); list.add(new BigDecimal(1)); list.add(new BigDecimal(2)); list.add(new BigDecimal(3)); // 要素の全てが0より大きければTrue boolean allMatch = list.stream().allMatch(value -> value.compareTo(BigDecimal.ZERO) > 0); System.out.println("allMatch: " + allMatch); // 要素のどれかが3と等しければTrue boolean anyMatch = list.stream().anyMatch(value -> value.compareTo(new BigDecimal(3)) == 0); System.out.println("anyMatch: " + anyMatch); // 要素の中に0未満のものが1つも含まれないならTrue boolean noneMatch = list.stream().noneMatch(value -> value.compareTo(BigDecimal.ZERO) < 0); System.out.println("noneMatch: " + noneMatch); // 要素の全てが1より大きければTrue boolean allMatch2 = list.stream().allMatch(value -> value.compareTo(BigDecimal.ONE) > 0); System.out.println("allMatch2: " + allMatch2); // 要素のどれかが0と等しければTrue boolean anyMatch2 = list.stream().anyMatch(value -> value.compareTo(BigDecimal.ZERO) == 0); System.out.println("anyMatch2: " + anyMatch2); // 要素の中に1以下のものが1つも含まれないならTrue boolean noneMatch2 = list.stream().noneMatch(value -> value.compareTo(BigDecimal.ONE) <= 0); System.out.println("noneMatch2: " + noneMatch2);
allMatch: true anyMatch: true noneMatch: true allMatch2: false anyMatch2: false noneMatch2: false
Streamが持つ要素数を返すメソッド
次はStreamの要素数を返すメソッドを見てみましょう。
戻り値 | メソッド | 概要 |
---|---|---|
long | count() | Streamが持つ要素の個数を返す |
List<BigDecimal> list = new ArrayList<>(); list.add(new BigDecimal(1)); list.add(new BigDecimal(2)); list.add(new BigDecimal(3)); long count = list.stream().count(); System.out.println("count: " + count);
count: 3
数値の集計を行うメソッド
Streamから拡張されたプリミティブな数値の要素を持つStream(IntStream、LongStream、DoubleStream)では次の集計結果を返すメソッドがあります。
戻り値 | メソッド | 概要 |
---|---|---|
int / long /double | sum() | Streamが持つ要素の合計を返す。戻り値はそのStreamが表すものになる。要素がない場合は0を返す |
OptionalDouble | average() | 平均値を返す。要素がない場合はEmptyなOptionalDoubleを返す。割り切れない場合はdouble値で表現できる値に丸められる |
List<BigDecimal> list = new ArrayList<>(); list.add(new BigDecimal(1)); list.add(new BigDecimal(2)); list.add(new BigDecimal(3)); int[] intValues = {1, 2, 3}; long[] longValues = {1L, 2L, 3L}; double[] dblValues = {0.1, 0.2, 0.3}; System.out.println("----- sumメソッド -----"); IntStream intStream = Arrays.stream(intValues); int intSumResult = intStream.sum(); System.out.println("intStream.sum(): " + intSumResult); LongStream longStream = Arrays.stream(longValues); long longSumResult = longStream.sum(); System.out.println("longStream.sum(): " + longSumResult); DoubleStream doubleStream = Arrays.stream(dblValues); double doubleSumResult = doubleStream.sum(); System.out.println("doubleStream.sum(): " + doubleSumResult); System.out.println("----- averageメソッド -----"); System.out.println("Arrays.stream(intValues).average(): " + Arrays.stream(intValues).average()); System.out.println("Arrays.stream(longValues).average(): " + Arrays.stream(longValues).average()); System.out.println("Arrays.stream(dblValues).average(): " + Arrays.stream(dblValues).average());
----- sumメソッド ----- intStream.sum(): 6 longStream.sum(): 6 doubleStream.sum(): 0.6 ----- averageメソッド ----- Arrays.stream(intValues).average(): OptionalDouble[2.0] Arrays.stream(longValues).average(): OptionalDouble[2.0] Arrays.stream(dblValues).average(): OptionalDouble[0.19999999999999998]
この実行結果から分かる通り、double値で計算する場合、2進数と10進数での変換時の誤差が発生するので注意してください(※sumメソッドでも、例えば「double[] dblValues = {0.1, 0.7, 0.3};」とした場合、意図した結果になりません)。
要素を配列として返すメソッド
次はStreamが持っている要素を配列にして返すメソッドを見てみましょう。
戻り値 | メソッド | 概要 |
---|---|---|
Object[] | toArray() | Streamが持つ要素をObjectの配列にして返す |
T[] | toArray(IntFunction<T[]> intFunction) | intFunctionの引数にStreamが持つ要素数を渡しStream が持つ要素のTの型の配列にして返す |
String[] values = {"あ", "い", "う", "え", "お"}; System.out.println("----- toArray() -----"); Stream<String> stream = Arrays.stream(values); Object[] objects = stream.toArray(); for (Object result : objects) { System.out.println("toArray(): " + result); } System.out.println("----- toArray(IntFunction<T[]>) -----"); Stream<String> stream2 = Arrays.stream(values); String[] strings = stream2.toArray(count -> { System.out.println("count=" + count); return new String[count]; }); for (String result : strings) { System.out.println("toArray(IntFunction): " + result); }
----- toArray() ----- toArray(): あ toArray(): い toArray(): う toArray(): え toArray(): お ----- toArray(IntFunction<T[]>) ----- count=5 toArray(IntFunction): あ toArray(IntFunction): い toArray(IntFunction): う toArray(IntFunction): え toArray(IntFunction): お
次回は、ラムダ式と関連の深いメソッド参照とコンストラクタ参照
今回はJava 8の新機能であるStream APIの主なメソッドについて見てきました。サンプルを見て分かるように、ラムダ式を使うことによってStream APIの関数型インターフェースの実装を簡潔にできるようなっています。
次回は、さらに今回紹介しきれなかったStream APIのその他のメソッド、およびラムダ式と関連の深いメソッド参照とコンストラクタ参照を見ていきます。ご期待ください。
著者プロフィール
長谷川 智之(はせがわ ともゆき)
株式会社ビーブレイクシステムズ開発部所属。
社内サークル執筆チーム在籍。
主な執筆。
@IT連載『Javaの常識を変えるPlay framework入門』
日経ソフトウェア連載『コツコツ学ぶAndroidネイティブアプリ開発教室』
Copyright © ITmedia, Inc. All Rights Reserved.
関連記事
- JavaOne Tokyo 2012まとめレポート(後編):ラムダ式、JAR脱獄、JavaScript/■■Node.jsに接近するJDK 8、そして9へ
JDK 8の新機能のうち、Lambda、Jigsaw、Nashorhについて解説した講演を詳細にレポートする。そしてJava SE 9はどうなる? - スケーラブルで関数型でオブジェクト指向なScala入門(4):基本的なパターンマッチとScalaで重要な“関数”
match構文、関数の定義と呼び出し、高階関数、プレイスホルダ構文、部分適用、クロージャなどを紹介します - 「Javaに並列処理と関数型言語の要素を」、ティム・ブレイ氏
- いよいよ始まるRuby 1.9への移行:関数型っぽくなったRuby 1.9
- WebSocketやREST APIのサポート強化:Java 8&Java EE 7に対応した「Spring Framework 4.0」正式版リリース
米Pivotalは2013年12月12日、オープンソースのJavaアプリケーションフレームワーク「Spring Framework 4.0」の正式版をリリースした。 - JDK 8、TLS 1.2がデフォルトに
Javaの通信暗号化もTSL 1.2に。基本的に後方互換性は維持するが、一部影響がある場合もあるという。 - .NET開発『虎の巻』:C#ラムダ式 基礎文法最速マスター
ラムダ式(C#)の基礎文法を、短い説明と簡単なコードで簡潔にまとめる。「ラムダ式、どう書くんだっけ?」という場合の簡易リファレンスとして活用できる - .NET開発『虎の巻』:VBラムダ式 基礎文法最速マスター
今度はVB。ラムダ式の基礎文法を、短い説明と簡単なコードでまとめる。「ラムダ式、どう書くんだっけ?」という場合の簡易リファレンスとして活用できる - 特集:C#開発者のためのF#入門(前編):F#で初めての関数型プログラミング
アルゴリズム実装などに威力を発揮する、関数型プログラミングの基礎やF#言語の特徴を解説。C#開発者なら、ここから始めよう! - Gaucheでメタプログラミング(1):ちょっと変わったLisp入門
Lispの一種であるScheme。いくつかある処理系の中でも気軽にスクリプトを書けるGaucheでLispの世界を体験してみよう