Java
Java9

java9のお勉強(dropWhileとtakeWhileとStream.ofNullable)

More than 1 year has passed since last update.

ということで件名の内容を書こうと思うのですが
こちらの素晴らしい投稿がとてもわかり易いので、何か今更投稿することもない気がしてきました。

とりあえず軽くやってみました。

        List<String> list = Arrays.asList("AA", "BB", "C", "DD", "E", "FGH");
        List<String> list2 = Arrays.asList("A", "B", "C", "DD", "E", "FGH");

        System.out.println("とりあえず何も考えずに出す");
        list.stream().forEach(System.out::print);


        System.out.println("\n2文字以上のものはスキップしてから出す");
        list.stream().dropWhile(str -> str.length() >= 2).forEach(System.out::print);

        System.out.println("\nlist2は最初が1文字から始まってからこいつに適用しても結果として何も変わらない");
        list2.stream().dropWhile(str -> str.length() >= 2).forEach(System.out::print);

実行結果

とりあえず何も考えずに出す
AABBCDDEFGH
2文字以上のものはスキップしてから出す
CDDEFGH
list2は最初が1文字から始まってからこいつに適用しても結果として何も変わらない
ABCDDEFGH

ポイントはdropWhileであってフィルターではないってところですかね。
自分で書いてみるまでは一番最後の

list2.stream().dropWhile(str -> str.length() >= 2).forEach(System.out::print);

は2文字以上の要素を全部除去してくれるのでABCEって出るものと思い込んでいたのですが、結果が違ったので何だろって思ったけど
list2を最初から読み込んでいって2文字以上のやつが出ている間は読み飛ばすぜっていうメソッドなので、最初の要素Aの段階ですでに2文字以上ではないから何もdropされなかったのは今思うと自然。

使い方は似た感じですがtakeWhileもやってみました。

        System.out.println("\ntakeWhileも似たような感じ");
        list.stream().takeWhile(str -> str.length() >= 2).forEach(System.out::print);

実行結果

takeWhileも似たような感じ
AABB

今回のラストはStream.ofNullable。

        /* Stream.ofNullableやるよ */
        List<String> list3 = Arrays.asList("A", "B", null, "DD", "E", "FGH");
        System.out.println("\n文字サイズ出します");
        // Stream.ofNullableしない例
        try {
            list3.stream().forEach(str -> System.out.println(str.length()));
        } catch (NullPointerException nullpo) {
            System.out.println("想定通りぬるぽ!");
        }

        // Stream.ofNullableする例(なお、Stream.ofNullable(str)をStream.ofNullable(str.length())とかやったら
        // ぬるぽで落ちます。あくまでofNullableの引数がNULLだったら飛ばすってだけなので。
        list3.stream().flatMap(str -> Stream.ofNullable(str)).forEach(str -> System.out.println(str.length()));

実行結果

文字サイズ出します
1
1
想定通りぬるぽ!
1
1
2
1
3

forEachのところで使いたい変数がNULLだったら飛ばすぜみたいに出来るので便利そうに見えるけど
いちいちflatMapとか書くの面倒だしそんなに使い勝手いいかって言うと・・・。
あと今回かなり適当な例ですが、実際は冒頭に書いた参考記事の例のようにMapから値が取れなかった場合に使ったりするほうがおそらく実際に使われると思います。