StreamAPI

Stream

Javaは学生以来殆ど書いたことないのですが、あの時習った時代からとても進化しており、Stream APIなんてものが追加されていました。
前回前々回と書いたmap処理みたいなことができるとのこと。
関数型プログラミングってやつみたいです。

Stream取得~中間処理~終端処理

Streamを使う時の流れは、以下のようになります。 1. 生成 2. 中間処理(filterかけたりmapしたり) 3. 終端処理(ListにしたりforEachかけたり) これだけ書いてもなんのことやら・・・コードを書いた方が分かりやすいですね。

List<Integer> data = Arrays.asList(0,1,2,3,4,5);//リストを宣言
List<Integer> stream_data = data.stream() //生成
                            .map(value->value*2) //中間処理
                            .toList(); // 終端処理
System.out.println(stream_data);//[0, 2, 4, 6, 8, 10]

生成して~map書いて~リストにする。javascriptではmapすると配列が帰ってきましたが、Streamでのmapは、Streamを返します。
そのため、StremをリストにするtoList()を最後に記載しています。
ただ、toList()で帰ってきたリストは更新ができないので、更新したい場合はこんな書き方になります。

List<Integer> data = Arrays.asList(0,1,2,3,4,5);//リストを宣言
List<Integer> stream_data = data.stream() //生成
                            .map(value->value*2) //中間処理
                            .collect(Collectors.toList()); // 終端処理
stream_data.set(1,3);
System.out.println(stream_data);//[0, 3, 4, 6, 8, 10]

終端処理を変えただけ。 filterを組み合わせることもできます。

List<Integer> stream_data = data.stream() //生成
                            .map(value->value*2) //中間処理
                            .filter(value->value%3 == 0) //中間処理
                            .collect(Collectors.toList()); // 終端処理
System.out.println(stream_data);//[0, 6]

Streamを生成することと、終端処理が必要なこと以外はjavascriptと殆ど一緒なので、理解はしやすいですね。
今回はリストを返却しただけでしたが、終端処理にはforEach、count、max・min(InsStreamにする必要がある)等色々あります。

連番のリストを作る

javascriptで連番の配列を作るとき、こんな書き方をしたらいけるよって記事を前々回書きました。

[...Array(5).keys()];
Array(5).fill(0).map((_,index)=>index);
// 0,1,2,,3,4

JavaでもStreamを使うことで可能になります。

List<Integer> lst = IntStream.range(0,5).boxed().toList();
System.out.println(lst);//[0,1,2,3,4]

IntStreamはStreamのint型。まずはこいつを生成します。
IntStreamはrangeメソッドを持っているので、値を入れて(0,1,2,3,4)を作ります。ここはjavascriptよりも分かりやすいですね。
次は見慣れないboxed()。IntStreamはtoList()やCollectors.toList()でリスト化できません。
なので、boxed()でIntStreamからStreamに変換をかけます。
最後にリスト化して終わり!
今回はリストにしただけだけど、もちろんmapと組み合わせることができます。

IntStream.rangeClosed(1,30).boxed().map(value-> {
    String result = "";
    result = value % 3 == 0 && value % 5 == 0 ? "FizzBuzz" :
             value % 3 == 0 ? "Fizz" :
             value % 5 == 0 ? "Buzz" :
             value.toString();
    return result;
}).forEach(System.out::println);

みんな大好きFizzBuzz。rangeClosed(1,30)で指定すると、1~30が対象になります。(rangeは1~29)
mapの中で参考演算子もりもり書いてFizzBuzz。最後はメソッド参照でprintlnして終わり!