Java 9 Stream 新機能
Java 9 でStreamに3つの機能が追加されますね。
・takeWhile 条件を満たす間のデータを対象とする
・dropWhile 条件を満たす間のデータを対象外とする
・ofNullable nullを許容する
でも新機能以前に仕事で Stream を使ってる人(というかソース)を見ないなーと思います。
(仕事だとあんまり新しいものを使う機会がない)
新しい物にも触れていかないと置いて行かれちゃいますのでどんなものか軽く調べてみました。
そもそも Stream ってどういうときに使うの?
多分こういう時に使うと思います。
・基本的に今までより少ない記述で書けるようになるので、ソースがスッキリする。
・色んなAPIの返却値が Stream になっていたりするので知らないとそもそも使えない。
・parallel()を使って並列処理を走らせたい。 (2017/06/01 追記)
・リストの中身を使って違うリストを作成する。(2017/06/02 追記)
どうやって Stream を使うの?
例1:リストをループしてメソッドに渡す
List<String> list = Arrays.asList("その1", "その2", "その3", "その4", "その5");
// Hogeクラスのfugaメソッドにリスト内の文字列を渡している
list.stream().forEach(Hoge::fuga);
例2:文字列リストから整数リストを作成
List<String> sl= Arrays.asList("11", "12", "13", "14", "15");
List<Integer> il = sl.stream().map(s -> Integer.parseInt(s)).collect(Collectors.toList());
例3:"C:\temp"以下のcsvのパスを全部取得後、"A"で始まるファイルの件数だけ取得
※Files.findは対象のパス、探す深度、マッチング条件を渡して Stream を返します。
Path target = Paths.get("C:\temp");
try(
Stream<Path> paths = Files.find(target , Integer.MAX_VALUE, (p, a) -> p.getFileName().endsWith(".csv"));
){
// 「A」で始まるCSVだけカウントしてみる
long c = paths.filter(p -> p.getFileName().startsWith("A")).count();
}
ちょこちょこ出てくる「 -> 」っていのは「ラムダ式」ってやつですね。
streamAPIはだいたい引数が Consumer になっていてメソッド参照とかラムダ式を渡せるようになっています。
まぁ「 -> 」が出てきたら左側が引数、右側はメソッドの中身が書いてあると思えば良いのではないでしょうか。
メソッド参照は「Hoge::fuga」という風に書いてある奴ですね。
読むだけなら「Hoge.fuga(str)」の括弧部分が省略されてると思えばいいと思います。
比較してみる
Stream を使うことでどれくらいソースが縮むのか書いてみましょう。
■ Stream を使う場合
paths.filter(p -> p.getFileName().startsWith("A"))
■ Stream を使わない場合
/** フィルターの部分 */
private List<Path> filter(List<Path> paths) {
List result = new ArrayList<>();
for (Path p : paths) {
if (isStartA(p)) {
result.add(p);
}
}
return result;
}
/** ラムダ式の部分 */
private boolean isStartA(Path p) {
return p.getFileName().startsWith("A");
}
Stream とラムダ式を使うことでいかに記述が減るか分かりますね!
まとめ
上記の結果を見ると Stream とかラムダ式をもっとバンバン使った方がいいじゃんって感じですが、
実際に仕事で使うとなると「for・while禁止」とかしないとソースが滅茶苦茶になってしまったりが悩みどころでしょうか
あとわかってない人には意味不明のソースになります。(これはわかってない人が悪い気もする)
せっかく便利にアップデートされていってるのだから人間のほうもアップデートしていきたいですね!