Steam APIとは?
- 繰り返し処理をサポートするライブラリ
- コレクション、配列、ファルなどデータの集合(データソース)から要素を取り出し処理の流れ(Stream)に引き渡す
Stream API基本
- データソースからのストリーム生成
-
中間処理(抽出・加工など)
- 戻り値は
Stream<T>
- 戻り値は
-
終端処理(出力・集計など)
- 終端処理のタイミングでストリーム一連の処理が実行(遅延処理)
- 中間/終端処理は型合致する標準ライブラリをメソッド参照可能
-
メソッドチェーン:ストリーム生成から中間処理/終端処理を
.
演算子で連結できる
import java.util.ArrayList;
import java.util.Arrays;
public class StreamBasic {
//データソース準備
public static void main(String[] args) {
var list = new ArrayList<String>(Arrays.asList("ant", "elephant", "hamster"));
/*ストリームによる処理
あらかじめ用意されたリストっからストリーム生成
ArrayList<String>を元にしているので
streamメソッドもStream<String>オブジェクトを返す
*/
list.
stream().
/*中間処理
filterメソッドで文字数3以上を取り出し、mapで大文字変換
戻り値はStream<T>
*/
filter(s -> s.length() > 3).
map(String::toUpperCase).
/*終端処理
forEachメソッドで与えられた値をSystem.out
*/
forEach(System.out::println);//ELEPHANT HAMSTER
}
}
ストリーム生成
コレクション、配列からストリーム生成
- リスト、配列、マップ内容をストリーム処理で出力できる
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
public class StreamBasic2 {
//リスト
public static void main(String[] args) {
var list = new ArrayList<String>(Arrays.asList("ant", "elephant", "hamster"));
list.stream().forEach(System.out::println);
// list.parallelStream().forEach(System.out::println);
System.out.println("---------------");
//配列
var data = new String[] { "バラ", "あさがお", "チューリップ" };
Arrays.stream(data).forEach(System.out::println);
System.out.println("---------------");
//マップ
var map = new HashMap<String, String>(
Map.of("orange", "みかん", "apple", "りんご", "strawberry", "いちご"));
map.entrySet().stream().forEach(System.out::println);
}
}
-
parallelStreamstreamメソッドの並列版
- リストマップのコレクションであればstreamをparallelStreamに変えたら並列処理可能になる
list.parallelStream().forEach(System.out::println)
引数/ラムダ式からストリーム生成
- Stream生成のためのファクトリーメソッド
ofメソッド
- 指定された可変長引数をストリームに変換
import java.util.stream.Stream;
public class StreamOf {
public static void main(String[] args) {
var stream = Stream.of("first", "second", "third");
stream.forEach(System.out::println); //first, second, third
}
}
generateメソッド
-
指定されたラムダ式の戻り値でストリーム生成
- ex: 1~100の乱数を生成、ストリーム化
- 無限にストリーム生成するので中間/終端処理で明示的に中断
- 以下の例ではlimit(10)で先頭10件のみ処理している
- アプリで乱数ストリーム生成するときは
Random.intsメソッド
import java.util.Random;
import java.util.stream.Stream;
public class Main {
public static void main(String[] args) throws Exception {
var stream = Stream.generate(() -> {
var r = new Random();
return r.nextInt(100);
});
stream.limit(10).forEach(System.out::println);
//46 24 42 80 61 67 69 22 85 1
}
}
iterateメソッド
-
指定された初期値とラムダ式でストリーム生成
- 最初に初期値、以降は直前の結果が渡される
- 以下の例では1を初期値として2倍ずつ増やした値を生成
import java.util.stream.Stream;
public class Main {
public static void main(String[] args) {
var stream = Stream.iterate(1, (num) -> {
return num * 2;
});
stream.limit(10).forEach(System.out::println);
//4 8 16 32 64 128 256 512
}
}
builderメソッド
- ストリーム組み立てるためのStream.Builderオブジェクト誠意せい
import java.util.stream.Stream;
public class Main {
public static void main(String[] args) {
var builder = Stream.builder()
.add("Munchkin")
.add("Siamese")
.add("Persian");
builder.build().forEach(System.out::println);
//Munchkin
//Siamese
//Persian
}
}
concatメソッド
- 複数のストリームを絵for都合して一個のストリームにまとめる
import java.util.stream.Stream;
public class Main {
public static void main(String[] args) {
var stream1 = Stream.of("Munchkin", "Siamese", "Persian");
var stream2 = Stream.of("Corgi", "Poodle", "Shiba");
Stream.concat(stream1, stream2).forEach(System.out::println);
// Munchkin Siamese Persian
// Corgi Poodle Shiba
}
}
基本型ストリームの生成
- 基本型に特化したIntStream/LongStream/DoubleStream
- of/generate/iterate/builderファクトリーメソッド使える
- IntStream/LongStreamではrangeメソッドが使える
//上限値あhストリームに含まれない
import java.util.stream.IntStream;
public class Main {
public static void main(String[] args) {
IntStream.range(10, 20)
.forEach(System.out::println); //10 11 12 13 14 15 16 17 18 19
}
}
- 上限も含めたい場合、rangeClosedメソッド
import java.util.stream.IntStream;
public class Main {
public static void main(String[] args) {
IntStream.rangeClosed(10, 20)
.forEach(System.out::println); //10 11 12 13 14 15 16 17 18 19 20
}
}