Java Stream のネスト展開を考える。

あるListを Stream で処理する時に要素1つが更に List などを走査時に取得して
全体のList として処理することを考える。
簡単なサンプルとして、String の split でどう書くかを確認しておくのが良いだろう。

List<String> list = List.of("1,2,3", "4,5,6", "7,8,9");
		
List<String> slist = list.stream().map(e->sampleList(e))
                 .flatMap(e->e.stream())
                 .collect(Collectors.toList());
public static List<String> sampleList(String str){
    return Arrays.stream(str.split(",")).collect(Collectors.toList());
}

これなら、slist は、

[1, 2, 3, 4, 5, 6, 7, 8, 9]

となる。
Java8 までなら、map と flatMap でこのようにすれば良いだろう。
Java16 からの mapMulti は、
mapMulti - Oboe吹きプログラマの黙示録
では、汎用的なネストの例を書いていたが、この1階層のネストしかないものなら、

private void expandList(Object e, Consumer<Object> c) {
    for (String ie : sampleList(e.toString())) {
        c.accept(ie);
    }
}

を用意して

List<String> slist = list.stream().mapMulti((a, b)->expandList(a, b))
          .map(e->e.toString()).collect(Collectors.toList());

mapMulti を使うことである。

これを実行するクラス名が ”Sample” として、static メソッドにして
メソッド参照にしたければ、、

public class Sample {
    public void exec() {
        
        List<String> list = List.of("1,2,3", "4,5,6", "7,8,9");
        
        List<String> slist = list.stream().mapMulti(Sample::expandList)
        .map(e->e.toString()).collect(Collectors.toList());
        
    }
    public static List<String> sampleList(String str){
        return Arrays.stream(str.split(",")).collect(Collectors.toList());
    }
    
    private static void expandList(Object e, Consumer<Object> c) {
        for(String ie : sampleList(e.toString())){
            c.accept(ie);
        }
    }
}

つまり、Java15 以前は、map と flatMap でごりごり書くしかないけど
Java16 からは、mapMulti で再帰 BiConsumer もしくは1回実行で
書けるということだ。