次は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の要素数を返すメソッドを見てみましょう。
| 戻り値 | メソッド | 概要 |
|---|---|---|
| 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ネイティブアプリ開発教室』
JavaOne Tokyo 2012まとめレポート(後編):ラムダ式、JAR脱獄、JavaScript/■■Node.jsに接近するJDK 8、そして9へ
スケーラブルで関数型でオブジェクト指向なScala入門(4):基本的なパターンマッチとScalaで重要な“関数”
WebSocketやREST APIのサポート強化:Java 8&Java EE 7に対応した「Spring Framework 4.0」正式版リリース
JDK 8、TLS 1.2がデフォルトに
Gaucheでメタプログラミング(1):ちょっと変わったLisp入門Copyright © ITmedia, Inc. All Rights Reserved.