引数が2つ以下の場合
Java8既存のFunctionインターフェースを使えば、うまく対応できます。
例:
1 | // 引数が1つしかない |
なお、既存のFunctionインターフェースを分かりやすくまとめてくれた図表を見つけましたので、転載します。
Java 8 Functional Interface Naming Guide
引数が3つ以上の場合
解決法1: 自作関数型インターフェース
Java8のFunctionインターフェースにはインプットが3つ以上のインターフェースが提供されていません。
ならば、Functionインターフェースを自作してみましょう。
実は、ありがたいことに、Java8がただ単純にインプットが3つ以上の関数型インターフェースを提供してないだけで、(少なくてもOracleとOpenJDKのJavaでは)複数の引数へ対応する準備が整っています。どういうことでしょうか?まず、BiFunctionのソースを見てみましょう。
1 |
|
肝心なのはR apply(T t, U u);
だけです。このapply関数がjava.lang.reflect.Proxy.KeyFactory#apply
で実装されています。
1 | private static final class KeyFactory |
ご覧のように、KeyXが存在していて、その中でfor文を使って、interfaceごとに読み込み、レファレンスを作っています。なので、自作関数型インターフェース内でFunctionやBiFunctionと似ている感じでapplyを使えば良いでしょう。
1 |
|
そして、このTriFunctionを使って、3つ以上の引数が存在するケースに対応すると、
1 | TriFunction<String, Integer, Integer, String> newSubString = (str, start, number) -> |
うーん、悪くありません。しかし、もし単純な処理を行いたいだけであれば、わざわざインターフェースを作るなんか少し面倒臭いでしょう。他に方法ないでしょうか。
解決法2: カリー化
JavaScriptの経験者であれば、既に思い付いたかもしれません。カリー化すればいいです。では、カリー化とは何でしょうか?
カリー化 (currying, カリー化された=curried) とは、複数の引数をとる関数を、引数が「もとの関数の最初の引数」で戻り値が「もとの関数の残りの引数を取り結果を返す関数」であるような関数にすること(あるいはその関数のこと)である。
Wikipediaより
要するに、Java 8では、関数が変数のように扱うことができますので、戻り値で関数を返す手法が利用できます。
1 | Function<String, Function<Integer, Function<Integer, String>>> newSubString = (str) -> (start) -> (number) |
一回目、二回目では関数が返され、そして実行スコップから出ていない為、前の変数がクロージャーで持っていて、次の処理でも使用されます。
こんな感じで既存インターフェースを使うだけで、複数の引数へ対応できるようになりました。