Function<T, R>の andThen における NullPointerException の回避

Function<T, R> andThen , compose は、
以前から、最初の apply 結果が null だったら、
NullPointerException になってしまう不満がありました。
よくありがちなデータ構造

import lombok.Data;
@Data
public class Bucket{
   private Drink drink;
}
import lombok.Data;
@Data
public class Drink{
   private String name;
}

の時、、

Function<Bucket, Drink> f1 = Bucket::getDrink;
Function<Drink, String> f2 = Drink::getName;

Bucketインスタンス bucket に対して andThenを使えば、

String name = f1.andThen(f2).apply(bucket);

compose を使うなら、

String name = f2.compose(f1).apply(bucket);

であるが、Bucket の Drink が null であれば、NullPointerException になってしまう。
という不満です。
単に、Function#apply の連結実行なら、下記のようなメソッドでも良いが、
これはあまりにもセンスがない

static <T,V,R> R getChain(T t,Function<T,V> before, Function<V,R> after) {
   return Optional.ofNullable(before.apply(t)).map(after::apply).orElse(null);
}

そこで考えました。
Function<T, R> を拡張して andThen , compose をオーバーライドして、
最初の apply 結果が、null の時の対処をしてあげます。

以下、
・andThen , compose オーバーライドでは、最初の apply 結果=null なら、
  null を返す Function ラムダ式を返す。
・引数追加の andThen , compose は、最初の apply 結果=null なら、
  最終的に求めたい型の値を指定するか、Supplier で取得させるように指定します。

import java.util.Objects;
import java.util.Optional;
import java.util.function.Function;
import java.util.function.Supplier;
/**
 * NullableFunction
 */
public interface NullableFunction<T, R> extends Function<T, R>{

   @Override
   default <V> Function<T, V> andThen(Function<? super R, ? extends V> after){
      Objects.requireNonNull(after);
      return (T t) -> Optional.ofNullable(apply(t)).map(after::apply).orElse(null);
   }
   default <V> Function<T, V> andThen(Function<? super R, V> after, V v){
      Objects.requireNonNull(after);
      return (T t) -> Optional.ofNullable(apply(t)).map(after::apply).orElse(v);
   }
   default <V> Function<T, V> andThen(Function<? super R, V> after, Supplier<V> sup){
      Objects.requireNonNull(after);
      return (T t) -> Optional.ofNullable(apply(t)).map(after::apply).orElse(sup.get());
   }

   @Override
   default <V> Function<V, R> compose(Function<? super V, ? extends T> before){
      Objects.requireNonNull(before);
      return (V v) -> Optional.ofNullable(before.apply(v)).map(e->apply(e)).orElse(null);
   }
   default <V> Function<V, R> compose(Function<? super V, ? extends T> before, R r){
      Objects.requireNonNull(before);
      return (V v) -> Optional.ofNullable(before.apply(v)).map(e->apply(e)).orElse(r);
   }
   default <V> Function<V, R> compose(Function<? super V, ? extends T> before, Supplier<R> sup){
      Objects.requireNonNull(before);
      return (V v) -> Optional.ofNullable(before.apply(v)).map(e->apply(e)).orElse(sup.get());
   }

   static <T,V,R> Function<T, R> bind(Function<T,V> before, Function<V,R> after){
      return (T t) -> Optional.ofNullable(before.apply(t)).map(after::apply).orElse(null);
   }
   static <T,V,R> Function<T, R> bind(Function<T,V> before, Function<V,R> after, R r){
      return (T t) -> Optional.ofNullable(before.apply(t)).map(after::apply).orElse(r);
   }
   static <T,V,R> Function<T, R> bind(Function<T,V> before, Function<V,R> after, Supplier<R> sup){
      return (T t) -> Optional.ofNullable(before.apply(t)).map(after::apply).orElse(sup.get());
   }
}

andThen , compose のメソッドが増えてしまいましたが、いろんな場面を考慮すると便利です。
さらに、2つの Functionを指定して実行させる Function をstatic メソッドとして提供します。

サンプル

NullableFunction<Bucket, Drink> f1 = Bucket::getDrink;

とあれば、、Bucket bucket に対して

String drinkName = f1.andThen(Drink::getName, ()->"Drink name is null").apply(bucket);

となります。