ラムダ式のちょっとした使い道

Java1.8でストリームやラムダに対応し、遅まきながら世間の流れである関数に手を出した昨今です。
関数いいですね。うん。
オブジェクト指向を知ったときに感じた感動と同じような感動を感じます。

とにかく処理が短くなる。見やすくなる。明確になる。バグがでにくくなる。
そんな印象です。
で、私が今こんな事に使っていますというちょっとした事を一つ、まとめて書いてみました。

---
## Lambda constructor

たとえば、引数が沢山あるデータエンティティ(Entity)があるとします。
それをインスタンス化してリスト化して返したいとします。

```java:sample1
Entity suzuki = new Entity("suzuki",30,......);
```

どの引数が何の値なのかさっぱりわからない・・・

```java:sample2
Entity suzuki = new Entity();
suzuki.setName("suzuki");
suzuki.setAge(30);
suzuki...
suzuki...
suzuki...
//and so on....
```
普通はこうするんでしょうけど、これも嫌いなんです。

```java:sample3
List<Entity> list = new ArrayList<>();
Entity e = new Entity();
e.setName("suzuki");
e.setAge(30);
e...
e...
e...
e.....
//and so on...
list.add(e);
e = new Entity();
e.setName("suzuki");
e.setAge(30);
e...
e...
e...
e...
e.....
//and so on...
list.add(e);
return list;
```
こういうのを見ると、頭を抱えてしまいます。
見るからにバグの温床の気がします。そこで

```java:sample4
Entity suzuki = MyObjects.instance(Entity::new , t -> {
   t.setName("suzuki");
   t.setAge(30);
   t...
   t...
   //and so on.
});
Entity yamada = MyObjects.instance(Entity::new , t -> {
   t.setName("yamada");
   t.setAge(30);
   t...
   t...
   //and so on.
});
return Arrays.asList(suzuki,yamada);
```

こんな風に書けたらいかがでしょうか？


```java:sample5
return Arrays.asList(
   MyObjects.instance(Entity::new , t -> {
      t.setName("suzuki");
      t.setAge(30);
      t...
      t...
      //and so on.
   }),
   MyObjects.instance(Entity::new , t -> {
      t.setName("yamada");
      t.setAge(30);
      t...
      t...
      //and so on.
   })
);
```

正直、sample5にする必要はあまり感じません。`asList`がどこまで繋がっているか分かりにくいと思います。
個人的にはsample4が好きです。

そういえば、fluentタイプってのもありましたね。

```java
Entity suzuki = EntityBuilder.new()
   .setName("suzuki")
   .setAge(30);
Entity yamada = EntityBuilder.new()
   .setName("yamada")
   .setAge(30);
return Arrays.toList(suzuki,yamada);
```

うん。美しいですね。ですが、こんなビルダーを全てのエンティティに用意している人はいないのではないでしょうか。
そういえばLombokに@Builderありますね・・・どうなんでしょう。
（しかし、よくよく考えると、setterの戻り値をvoidではなくthisを戻す決まりにしてしまえば、これ普通にできるのでは・・）

---
## Lambda setter.

今度はコンストラクタではなくセッターです。
値をセットするだけ。

```java:sample6
AAAAAAAAFactory factory = context.getFactory();
factory.setMax(100);
factory.setMin(10);
factory.setInitial(10);
```

AAAAAAAAFactoryなんて知りたくもないじゃないですか？

```java:sample7
MyObjects.set( context.getFactory() , f -> {
   f.setMax(100);
   f.setMin(10);
   f.setInitial(10);
});
```

このほうが分かりやすいと思うのですよ。
もしセットしたいものが一つならこうしますよね？

```java:sample8
context.getFactory().setMax(100);
```

いくつ値をセットする時でも、同じ事がしたいのです。

---
## 実装

```java:MyObjects.java
public class MyObjects{
   /**
    * lambda constructor.
    */
   public static <T> T instance(Supplier<T> sup, Consumer<T> init){
      T t = sup.get();
      init.accept(t);
      return t;
   }
   /**
    * lambda setter.
    */
   public static <T> void set(T t, Consumer<T> init){
      init.accept(t);
   }
}
```

ほとんど何もありません。

---
## 最後に

大したコードではないと思いますし、ラムダのおかげで凄い事ができたというわけでもありません。
ですが、私がこれまでJavaで嫌いだった様々な標準的なイディオムを消し去る事ができて、ラムダ様様です。

### わき道

```java
Entity suzuki = MyObjects.instance(Entity::new, t -> {
   t.name = "suzuki";
   t.age = 30;
});
```

Entityを変更せずにこう書けたら最高に幸せです。

```java
@Data
public class Entity{
   protected String name;
   protected int age;

   @FunctionalInterface
   public interface Initializer extends Cunsumer<Entity>{}
}
```
こんなエンティティを定義して

```java
Entity suzuki = MyObjects.instance(Entity::new, (Entity.Initializer) t -> {
   t.name = "suzuki";
   t.age = 30;
}
```
こんなことは出来ないわけではありません。でもこれ、さすがにアクセス修飾子がprivateではダメで、むしろ汚くなった気がします。という事で諦めました。

どなたか良い案があれば教えて下さい。