「Functional Interfaceやらなんやらが便利なのはなんとなくわかってきたんだ。でも、この "identity" ってやつは何に使うんだ? そのまま返すだけの関数を返すって一体何がしたいのさ?」
なんて言われたので、超今更なメモ。
注: 調査検証が雑です。マサカリ歓迎
// こんなクラスがあるとして
@Data
class Obj {
private int id;
private String data;
}
// List になってたとする
List<Obj> list = <some>;
// key:id, value:obj のマップを生成 (※もっとマシな手がありそうな気はする)
Map<Integer, Obj> map = list.stream().collect(Collectors.toMap(obj::getId, Function.identity()));
Functional Interface は「操作そのもの」を受け取るためのインターフェイスだ。ありとあらゆる操作をシグニチャでそれっぽく処置してくれる。
しかし、これをバンバン使って物を書いていくと「いやいやそのままでいいんだ!何もせんでくれ!」ってことはなくもない。そういう時に identity が役に立つ。
もちろん同じことは lambda で o -> o とか書いても出来るが、しかし、全く同じとは行かない。
lambda の実体は無名ローカルクラスだというのは有名な話だが、つまり使えば使うほどクラスとインスタンスが増える。ということは多少とは言え負荷がかかる。
(そりゃそうだよな、引数として渡せるってことはオブジェクトとしての実体があるってことだ)
一方 (JVM実装次第かもしれないが) identity は常に同一のインスタンスを返すそうだ:
https://stackoverflow.com/questions/28032827/java-8-lambdas-function-identity-or-t-t
確かに、確実に一発で終わるなら lambda でさらっと書いてもまあ困らない。しかし、基本的に Function.identity なり UnaryOperator.identity なりを使っておいたほうがうっかり無駄インスタンスを量産しなくて安心できる利点がある。ちょっとタイプ数と import が増えるのはまあ許してやろう。
「ところで identity ってなんだ?」
identity = 恒等。メソッド identity は恒等関数を返す。
恒等関数は「渡された引数を返す関数」で、関数の結合における単位元。つまり、 (本来は文脈の示す領域によるが、あくまで感覚的には) 数字の1みたいなもの。