JavaにおけるLambda式は、関数型プログラミングの思想を簡潔に表現するための構文です。従来の匿名内部クラスによる冗長な記述を大幅に削減し、コアとなる処理ロジックに焦点を当てたコード設計を可能にします。
関数型インターフェースの本質
関数型インターフェースとは、抽象メソッドが1つだけ定義されたインターフェースを指します。例えばjava.lang.Runnableやjava.util.function.Predicateなどが該当します。このようなインターフェースに対しては、Lambda式を用いてインスタンスを直接生成できます。
記述の進化:4段階の簡略化プロセス
以下の例では、Operationという単一抽象メソッドを持つインターフェースを基に、実装形態の変遷を示します:
interface Operation {
int compute(int x, int y);
}
public class LambdaEvolution {
// ① 明示的な実装クラス
static class BasicOperation implements Operation {
public int compute(int x, int y) { return x + y; }
}
// ② 静的ネストクラス
static class StaticOperation implements Operation {
public int compute(int x, int y) { return x * y; }
}
public static void main(String[] args) {
// ③ ローカルクラス(メソッド内定義)
class LocalOperation implements Operation {
public int compute(int x, int y) { return x - y; }
}
// ④ 匿名クラス → Lambdaへと移行する直前の形
Operation anon = new Operation() {
public int compute(int x, int y) { return x / y; }
};
// ⑤ Lambda式(完全展開形)
Operation lambda1 = (int a, int b) -> { return a % b; };
// ⑥ 簡略化その1:型推論によりパラメータ型省略
Operation lambda2 = (a, b) -> { return a & b; };
// ⑦ 簡略化その2:単一式なら波括弧とreturnキーワードを省略
Operation lambda3 = (a, b) -> a ^ b;
// 実行例
System.out.println(lambda3.compute(12, 5)); // 出力: 9
}
}
簡略化のルールと制約
- パラメータ型は、すべてのパラメータで同時に省略するか、すべて明示する必要があります(混合不可)
- パラメータが1つの場合は括弧を省略可能(例:
x -> x * 2) - ボディが単一の式のみの場合は波括弧と
returnを省略可能ですが、複数ステートメントを含む場合は必須です - Lambda式の使用には、対象インターフェースが確実に関数型であることが前提です(
@FunctionalInterfaceアノテーションでコンパイル時検証が可能です)
実用的な関数型インターフェースの活用
標準ライブラリのjava.util.functionパッケージには、代表的な関数型インターフェースが多数用意されています:
Function<T,R>: 引数1つ、戻り値あり(例:str -> str.length())Predicate<T>: 条件判定(boolean返却)Consumer<T>: 値を受け取って処理(戻り値なし)Supplier<T>: 値を生成・提供(引数なし)
これらのインターフェースとLambda式を組み合わせることで、コレクション操作や条件分岐などの処理を宣言的に記述できます。