再帰メソッドとラムダ式

再帰呼出しをするように関数型インターフェースを書くまでもない、
単にメソッド宣言を省略するだけの目的で考える。
再帰と言っても、実際の仕事の機会では、フィボナッチ数列を求めるような機会よりも
処理が遅くてもいい探索目的の機会の方が多い。

例題(簡単に紹介するための例題)
以下 Item オブジェクトの親子関係のリストからルートを求める

public class Item{
   public int id;
   public String name;
   public Integer parent;
   public Item(int id, String name, Integer parent){
      this.id = id;
      this.name = name;
      this.parent = parent;
   }
}

要件発生の都度、再帰メソッドを書く場合、、

static Item getRoot(Item item, List<Item> list){
   if (item==null || item.parent==null) return item;
   return getRoot(list.stream().filter(e->e.id==item.parent).findAny().orElse(null), list);
}

ジェネリックとBiFunction , Predicate で再帰メソッドを定義

import java.util.function.BiFunction;
import java.util.function.Predicate;
/**
 * Refrain
 */
public interface Refrain{

   public static <T, U> T call(T t, U u, BiFunction<T, U, T> f, Predicate<T> p){
      T r = f.apply(t, u);
      if (p.test(r)) return r;
      return  call(r, u, f, p);
   }
}

呼出し例

List<Item> list = new ArrayList<>();
list.add(new Item(1, "A", null));
list.add(new Item(2, "B", 1));
list.add(new Item(3, "C", 2));
list.add(new Item(4, "D", 3));
Item root = Refrain.call(item, list
   , (t, u)->u.stream().filter(e->t.parent != null && e.id==t.parent).findAny().orElse(null)
   , e->e==null || e.parent==null);

Refrain と、いいかげんに名前をつけました。
ふと、頭の中で浮かんだのが、ユーミンの「リフレインが、」・・・
世代がバレてしまいますね。