Functionの結果をBiConsumerで実行する

Webアプリ開発をしているとよく、画面プレゼンテーション層と
サービスロジック層の間の為にコンバータなるものを作らされたりして
面倒なものです。
よく書かされてしまう、getter で持ってきて、setter に食わせる
  a.setPhonNumber(b.getPhoneNumber());
みたいなものを大量に書かされて、まあコンパクトに書けないことはないんですけど、
単純に左から右へ渡すのでなく、加工などの処置が必要で
生成済インスタンスの状態毎に処置が必要な時は、面倒くさいものです。
先日の、new 演算子で生成する変数のコーディングを減らす方法 - Oboe吹きプログラマの黙示録
に触発されて、
名称はさておき、以下を考えました。。。

getterとして、Function<T, R> で取得して、setter として BiConsumer を実行します。

import java.util.function.BiConsumer;
import java.util.function.Function;

@FunctionalInterface
public interface ApplyBiConsumer<T, U>{
   void accept(T t, U u);

   static <T, U, V> ApplyBiConsumer<T, U> of(Function<T, V> f, BiConsumer<U, V> c) {
       return (t,u)->{
          c.accept(u, f.apply(t));
       };
   }
}

使用サンプルは以下のとおりです。

import lombok.Data;
@Data
public class Foo{
   private String name;
   private int id;
   private LocalDate birthday;
}

import lombok.Data;
@Data
public class Person{
   private String name;
   private int id;
   private LocalDate birthday;
   private String info;
}
Foo foo;       // Foo のインスタンス
Person person; // Person のインスタンス
// TODO foo と person のインスタンス生成、

// foo から person へ情報をセット

ApplyBiConsumer.of(Foo::getName, Person::setName).accept(foo, person);
ApplyBiConsumer.of(Foo::getId, Person::setId).accept(foo, person);
ApplyBiConsumer.of(Foo::getBirthday, Person::setBirthday).accept(foo, person);

// 型が違うものをセットする例
ApplyBiConsumer.of(e->((Foo)e).getDay().format(DateTimeFormatter.ofPattern("yyyy年MM月dd日"))
            , Item::setInfo).accept(foo, person);
            
// もしくは、BiConsumer の方で対処する場合、、
ApplyBiConsumer.of(Foo::getDay, (t, u)->{
   ((Person)t).setInfo(((LocalDate)u).format(DateTimeFormatter.ofPattern("yyyy年MM月dd日")));
}).accept(foo, person);

a.setPhonNumber(b.getPhoneNumber()); の記述形式の方が短いと言えますが、
ラムダ式で書けるということは、変換式をsetter である BiConsumer の実行まで待てるので、
以下のように、この ApplyBiConsumer をリストに溜めてから実行できます。

List<ApplyBiConsumer<Foo, Person>> alist = Arrays.asList(
   ApplyBiConsumer.of(Foo::getName, Person::setName),
   ApplyBiConsumer.of(Foo::getId, Person::setId),
   ApplyBiConsumer.of(Foo::getBirthday, Person::setBirthday)
);

を用意しておけば、(Java11なら、List.of() で書くと思います。)

alist.stream().forEach(e->e.accept(foo, person));

のように、いつでもセットを実行できるわけです。

でも、この ApplyBiConsumer は、以下のように、BiConsumer 継承したものとして、
定義した方が良いのかもしれません。
継承なら、 void accept(T t, U u); を以下のとおりここでは書かないです。

import java.util.function.BiConsumer;
import java.util.function.Function;

@FunctionalInterface
public interface ApplyBiConsumer<T, U> extends BiConsumer<T, U>{
   static <T, U, V> ApplyBiConsumer<T, U> of(Function<T, V> f, BiConsumer<U, V> b) {
       return (t,u)->{
          b.accept(u, f.apply(t));
       };
   }
}

最終的には、後日投稿の以下がベスト
Functionの結果をBiConsumerで実行する(3) - Oboe吹きプログラマの黙示録