Java ラムダ式 (Lambda Expressions)
1. Java ラムダ式とは
ラムダ式(Lambda Expressions)は Java 8 で導入された機能です。
ラムダ式は、パラメータを受け取り値を返す短いコードブロックです。メソッドに似ていますが、名前を必要とせず、メソッドの本体の中に直接記述できるという特徴があります。
2. 構文(Syntax)
最もシンプルなラムダ式は、単一のパラメータと一つの式で構成されます。
parameter -> expression
複数のパラメータを使用する場合は、括弧で囲みます。
(parameter1, parameter2) -> expression
シンプルな式は即座に値を返す必要があります。ループや if 条件などの複数のステートメントを含めることはできません。より複雑な処理を行うには、波括弧 {} を使用してコードブロックを作成します。値を返す必要がある場合は、return キーワードを使用します。
(parameter1, parameter2) -> {
// コードブロック
return result;
}3. ラムダ式の使用方法
ラムダ式は、メソッドの引数として渡されることがよくあります。例えば、ArrayList の forEach() メソッド内でラムダ式を使用できます。
3.1 コード例:forEach() での利用
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
ArrayList<Integer> numbers = new ArrayList<Integer>();
numbers.add(5);
numbers.add(9);
numbers.add(8);
numbers.add(1);
// 各要素 n を出力するラムダ式
numbers.forEach((n) -> { System.out.println(n); });
}
}4. 変数への格納
ラムダ式は変数に格納することができます。ただし、その変数の型は、抽象メソッドを一つだけ持つインターフェース(関数型インターフェース / Functional Interface)である必要があります。また、ラムダ式はそのメソッドのパラメータと戻り値の型に一致していなければなりません。
Java には、リストで使用される java.util.function パッケージの Consumer など、多くの組み込み関数型インターフェースが含まれています。
4.1 コード例:Consumer 変数への格納
import java.util.ArrayList;
import java.util.function.Consumer;
public class Main {
public static void main(String[] args) {
ArrayList<Integer> numbers = new ArrayList<Integer>();
numbers.add(5);
numbers.add(9);
numbers.add(8);
numbers.add(1);
// ラムダ式を変数 method に格納
Consumer<Integer> method = (n) -> { System.out.println(n); };
numbers.forEach(method);
}
}5. メソッドパラメータとしてのラムダ式
ラムダ式をメソッドに渡すことも可能です。そのメソッドのパラメータは関数型インターフェースである必要があります。インターフェースのメソッドを呼び出すことで、渡されたラムダ式が実行されます。
5.1 コード例:自作インターフェースでの利用
// 関数型インターフェースの定義
interface StringFunction {
String run(String str);
}
public class Main {
public static void main(String[] args) {
// 異なる処理を行うラムダ式を定義
StringFunction exclaim = (s) -> s + "!";
StringFunction ask = (s) -> s + "?";
printFormatted("こんにちは", exclaim);
printFormatted("こんにちは", ask);
}
// 関数型インターフェースを引数に取るメソッド
public static void printFormatted(String str, StringFunction format) {
String result = format.run(str);
System.out.println(result);
}
}6. 匿名クラス vs ラムダ式
Java 8 以降では、多くの場合、匿名クラス(Anonymous Class)をラムダ式に置き換えることができます。ただし、これが可能なのはインターフェースが関数型インターフェース(抽象メソッドが一つだけ)である場合に限られます。
6.1 匿名クラスによる実装
// 関数型インターフェース(抽象メソッドが一つ)
interface Greeting {
void sayHello();
}
public class Main {
public static void main(String[] args) {
Greeting g = new Greeting() {
public void sayHello() {
System.out.println("匿名クラスからの挨拶");
}
};
g.sayHello();
}
}6.2 ラムダ式による実装
// 同じ関数型インターフェース
interface Greeting {
void sayHello();
}
public class Main {
public static void main(String[] args) {
// ラムダ式で簡潔に記述
Greeting g = () -> System.out.println("ラムダ式からの挨拶");
g.sayHello();
}
}6.3 使い分けの指針
- ラムダ式: 短く、単一のメソッドを持つインターフェースの実装に適しています。
- 匿名クラス: 複数のメソッドをオーバーライドする必要がある場合、フィールドを追加する場合、またはクラスを継承する場合には匿名クラスを使用します。