業務ロジックにありがちなListのインデックスに応じて処理を分ける処理はreduceを使って実装することもできる
例えば
「リストの先頭以外には:を付加する」
といったロジックはreduceを使って、下記のように実装することができる
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)に対して破壊的な操作を行っているため、改良版を書いてみる
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;
}
}