ラムダ式とは
実装が必要なメソッドを1つだけ持つインターフェース型変数に、実行したいコードを代入する仕組み。
関数型インターフェースとは
関数型インターフェースは、実装が必要なメソッドを1つだけ持つインターフェースのこと。
入力に対して出力が1つに決まるから「関数型」と呼ばれる。
関数型インターフェースの種類
インターフェースの種類 | 実装が必要なメソッド | 特徴 |
---|---|---|
Consumer<T> | void accept(T) | 引数を受け取って処理する。結果を戻さない、引数の消費者 |
Supplier<T> | T get() | 何も受け取らずに結果だけを戻す供給者 |
Predicate<T> | boolean test(T) | 引数を受け取って、それを評価する断定者 |
Function<T, R> | R apply(T) | 引数を受け取って、指定された型(R)の結果を戻す処理者 |
※<T>とは:TはTypeの略。何型でも良い、ということを汎用化して表している。
関数型インターフェースの例
・java.util.ListインターフェースのforEachメソッドはConsumer型のラムダ式を受け取れる
参考)
公式ドキュメント・インターフェースList<E>
公式ドキュメント・forEach
例)
public static void main(String[] args){
List<Integer> list = List.of(1,2,3);
list.forEach((x) ->{System.out.println(x)}); //引数を受け取って処理し値はreturnしない
}
・java.lang.StringクラスのtoUpperCaseメソッドはFunction型のラムダ式を受け取れる
例)
public static void main(String[] args){
Function<String, String> func = (x) -> {return x.toUpperCase();}; //引数を受け取って、指定された型の結果を戻す
System.out.println(func.apply("hello world"));
}
ラムダ式の書き方
<基本>
関数型インターフェースの型 変数名 = (引数) -> { //処理 return };
Function<String, String> func = (x) -> { return x.toUpperCase(); };
<引数が1つの時、()の省略>
関数型インターフェースの型 変数名 = 引数 -> { //処理 return };
Function<String, String> func = x -> { return x.toUpperCase(); };
<処理が1つの時、{}の省略>
関数型インターフェースの型 変数名 = 引数-> //処理;
※return文を書けない!!
list.forEach( x -> System.out.println(x) );
ラムダ式の注意点
【ラムダ式が持つ仮引数は、定数か実質的に定数】
・コンパイルエラー例(Java Silver黒本より)
void sample(){
int i = 0;
Supplier<Integer> foo = () -> i;
i++; //iは実質的に定数である必要
System.out.println(foo.get());
}
【引数のデータ型に注意】
ラムダ式の変数宣言はデータ型の指定を省略できる。
代入しようとしている関数型インターフェースの型から引数の型を推論できるため。
ラムダ式の変数を引数を、型を省略して書いたとしても、それは新しく定義された変数ということになる
→ラムダ式のスコープ内にある、既存の変数と重複しないか要確認!!
・コンパイルエラー例
final String val = "Hello World";
Consumer<String> func = (val) -> System.out.println(val); //ラムダ式のvalと、ローカル変数のvalで名前の重複がおこりコンパイルエラー
【スコープに注意】
ラムダ式のスコープは、ラムダ式が書かれているブロック全体におよぶ
・コンパイルエラー例
public class Main{
public static void main(String[] args){
Srting val = "A"; //ラムダ式のスコープ内にあるローカル変数val
Function f = (val) -> { //ラムダ式の変数val
System.out.println(val);
};
}
}
今後の課題
正直なところラムダ式についてまだまだ全然理解できていない・・・。
ラムダ式の仕組みについて、下記のサイトを理解したいと思う。
また、実際にどんな時にラムダ式を使うのかいまいち理解できていない。
ラムダ式を受け取ることができるメソッドは何なのか?
再利用しない簡単な処理を記述する際にはいつでも利用できるのか?
関数型インターフェースのメソッドでないと使えないのか?関数型インターフェースのメソッドであるとどう見分けるのか?
などなど、理解できていないことがたくさんある。