Java
java8,streamAPI

java8StreamAPI :: reduceによるListの操作

業務ロジックにありがちなListのインデックに応じて処理を分ける処理はreduceを使って実装することもできる
例えば
「リストの先頭以外には:を付加する」
といったロジックはreduceを使って、下記のように実装することができる

MyBusinessLogic.java
package test;

import java.util.ArrayList;
import java.util.List;
import java.util.function.BiFunction;
import java.util.stream.Stream;

public class MyBunessLogic {
    public static void main(String args[]){
        final BiFunction<List<String>, String, List<String>> operation = 
                (accum, value) -> {
                    if(accum.size()!=0)accum.add(" : "+value);
                    else accum.add(value);
                    return accum;
        };
        Stream.of("start","middle","end")
        .reduce(new ArrayList<String>(),operation,(s,v)->s)
        .forEach(System.out::print);
    }
}
出力結果
start : middle : end

追記
BiFunctionの型の意味が分かりにくいので、その用途をメモする
ジェネリックの1番目と2番目の型は関数の引数の型で、1番目はアキュームレーター、2番目は演算の対象になる値が設定される。
ジェネリックの3番目の型は関数が実行された時の戻り値を示している

追記2
reduceの3番目の引数に渡すラムダ式はStreamクラスのpararellメソッドを実行したときに呼び出されるが、サンプルの例だと適当な式を与えている。
というのも上記の例だと、そもそもListを順番に処理することを目的としており、並行処理で処理することを目的としていないからだ。
個人的にはreduceメソッドに並行稼働を目的としないメソッド、(U indentity,BiFunction<U,T,U> func)のオーバーロードがあれば便利だと思うが。

追記3
上記の例だとラムダ式の引数で渡している変数(accum)に対して破壊的な操作を行っているため、改良版を書いてみる

MyBunessLogic.java
package test;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;

public class MyBunessLogic {
    public static void main(String args[]){
        Stream.of("start","middle","end")
        .reduce(new ArrayList<String>(),MyBunessLogic::operate,(s,v)->s)
        .forEach(System.out::print);
    }

    private static  List<String> operate(List<String> accum,String value){
        List<String> list = new ArrayList<String>(accum);
        if(list.size()!=0)list.add(" : "+value);
        else list.add(value);
        return list;
    }
}