エンターテイメント!!

遊戯王好きのJavaエンジニアのブログ。バーニングソウルを会得する特訓中。

今更だが、JavaのStream.reduceで迷った

きっかけ

Javascriptのreduceのような実装をしたくて、いろいろ試して、かなり迷ったから書く。

Array.prototype.reduce() - JavaScript | MDN

詳細

やりたきこと

小計みたいなやつを出したかった。
なお、小計は、流れてくる要素とは別の方をしている。

迷った所

日本語がわからない

APIのリファレンス参照したけど、日本語がさっぱり分からなかった。。。
単位元の値って何?それって中国語?って感じでしたわ。。。

わかったこと

<U> U reduce(U identity,
             BiFunction<U,? super T,U> accumulator,
             BinaryOperator<U> combiner)

identity:初期値。
あれだ、for文の for(int i = 0; ;)i=0 のところって意味だろう。

accumulator:UとTを引数に、Uの型を返す。
これは、要するに、初期値に対して、何かしら要素を使って操作して、初期値と同じ型の計算した結果を返すってことね。

combiner:よく分かりません。。。
調べると、途中経過を合算するやつらしいね。
おそらく、並列処理する場合に必要になると思う。
試しに順次処理で実行してみたら、見事に呼ばれませんでしたわ。。。

感想

非常に厄介。。。
かなり癖がある。

Javascriptのreduceみたいに直感的だったら良かったのだが、わざわざいらない関数を定義しなきゃいけないのにかなり困惑した。
これ、初期値が型違いで、第三引数ないバージョン作れないのだろうか?
並列処理で呼んだらエラー吐くようにすれば、いけそうな気がしないでもない。

試したコード

実験のためにこねくりましていたコード。
たぶん、これでやりたいことは、調べられるはず。

import java.util.stream.IntStream;

public class Test {

    public static void main(String[] args) {
        double r = IntStream.of(1, 2, 3, 5).mapToObj(Work::new).reduce(0.2, (Double d, Work w) -> {
            return d + w.a;
        }, (o1, o2) -> {
            return null;
        });
        System.out.println(r);
    }
}

class Work {
    int a;
    public Work(int a) {
        this.a = a;
    }
}

参考サイト

Java Streamメモ(Hishidama's Java8 Stream Memo)

Java8のStreamを使いこなす - きしだのはてな

Stream (Java Platform SE 8)