#はじめに
・StreamAPIの代表的なメソッドと、基本的なコーディング例を示します。
・StreamAPIの考え方や応用例、テクニックについては他のエントリーへ委譲し、ここではできるだけシンプルに書くように努めます。
・Streamはラムダ式またはメソッド参照を与えて書くのが一般的ですが、あえて関数型インタフェースを宣言します。
#StreamAPIとは
・SE8で追加された、データの集合を扱うためのAPI。主な目的は並列処理への対応。StreamAPIを用いると、順次処理から並行処理への切替えが容易になる。
・java.util.streamパッケージ配下のインタフェースのことであり、java.ioパッケージで用いるストリームとは別物。
・java.util.streamパッケージは、BaseStreamインタフェースを基底として、参照型を扱うためのStreamインタフェースと、プリミティブ型を扱うための3つのインタフェースにより構成される。
・StreamはListやMapなどのデータ集合をもとに生成し、0回以上の中間操作と、1回の終端操作を実行することで結果を得る。
###より詳しく
Java(tm) Platform Standard Edition 8 パッケージ java.util.stream
Java Stream APIをいまさら入門 - 基本編
Java8 Streamざっくりまとめ
#生成
####参照型Stream
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
Stream<Integer> stream = list.stream();
####プリミティブ型Stream
IntStream intStream = IntStream.of(1, 2, 3, 4, 5);
####配列から
int[] array = { 1, 2, 3, 4, 5 };
IntStream intStream = Arrays.stream(array);
####レンジを指定して
IntStream intStream = IntStream.range(1, 5);
####ファイルから
Path path = Paths.get("D:\\hoge.txt");
Stream<String> fileStream = Files.lines(path)
###最も単純なStream操作
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
Stream<Integer> stream = list.stream();
stream.forEach(System.out::println);
Integer型のStreamを生成し、中間操作0回、終端操作1回で、標準出力処理を実行する。
forEachは終端操作。終端操作については後述。
基本的には、これに任意の回数の様々な中間操作と、同じく様々な終端操作のうちいずれか1回を組み合わせて利用する。
###より詳しく
Java 8 Stream API にテキストを流してみる(生成編)
#中間操作
####フィルタリング
Stream<String> stream = Stream.of("A", "B", "A", "B", "B", "A");
Predicate<String> isA = "A"::equals;
stream.filter(isA).forEach(System.out::println);
Predicate型のisHogeHogeを間に掛けてFalseを間引くイメージ。
Predicateは関数型インタフェース。
関数型インタフェースについては以下。
3分でわかる基本の関数型インタフェース
####マッピング
Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5);
Function<Integer, Integer> toDouble = param -> param * 2;
stream.map(toDouble).forEach(System.out::println);
Streamの各要素をキーとして、対応する値のStreamを返す。
要は変換処理みたいなもの。
サンプルはわかりやすくFunctionを使ったが、この場合はUnaryOperatorがスマート。
ラムダ式については以下。
Java8 Lambdaの文法拡張まとめ
インタフェースの実装がラムダになるまで
####ソート
Stream<Integer> stream = Stream.of(3, 2, 1, 5, 4);
Comparator<Integer> comparator = Comparator.reverseOrder();
stream.sorted(comparator).forEach(System.out::println);
sortedにcomparatorを与えることで、順序を指定する。
Comparatorについては以下。
(o1, o2) -> o1 - o2 なんて呪文はもうやめて! - Java8でのComparatorの使い方
#終端操作
####マッチング
Stream<String> stream = Stream.of("George", "John", "Ringo", "Paul");
Predicate<String> isRingo = "Ringo"::equals;
boolean isMatch = stream.anyMatch(isRingo);
allMatch、noneMatchなどのバリエーションもある。
####カウント
Stream<String> countSt = Stream.of("George", "John", "Ringo", "Paul");
long result = countSt.count();
####リダクション
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
Stream<Integer> stream = list.stream();
BinaryOperator<Integer> sum = Integer::sum;
Optional<Integer> result = stream.reduce(sum);
畳み込みなど、結果を単一の値へ処理する。
戻り値はOptional。Optionalについては以下。
Java 8 "Optional" ~ これからのnullとの付き合い方 ~
####可変リダクション
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
Stream<Integer> stream = list.stream();
List<Integer> resultList = stream.collect(Collectors.toCollection(ArrayList::new));
resultList.forEach(System.out::print);
ArrayListなど、集合へ処理する。
###より詳しく
Java 8 Stream API にテキストを流してみた(終端操作編)
Java8 Streamのリダクション操作について
#並列処理
Stream<String> stream= Stream.of("A", "B", "C", "D", "E", "F");
stream.parallel().forEach(param -> System.out.println(param + " thread-id: " + Thread.currentThread().getId()));
生成時にpararelStream()を使うか、中間操作でparallel()を噛ませるだけで並列処理になる。
###より詳しく
さあ、並列プログラミングをはじめよう
Java8のStreamとParallelStreamの使い分けについて
streamとparallelStreamについての考察
Java それぞれ書き方でどれほどパフォーマンスが違うのか?計測比較してみた。Streamとループとか
並列処理は書ききれないので深くは触れません。