ラムダ式を使ってリストの要素を全て出力する
for文を使わずにリストの全要素を出力する。
CollectionクラスのforEachメソッドとラムダ式を使う。
String[] arr = {"A","B","C"};
ArrayList<String> list = new ArrayList<>(Arrays.asList(arr));
list.forEach( str -> System.out.println(str) );
/*
実行結果
A
B
C
*/
ラムダ式の省略
ラムダ式は特定の条件の下で () や {} を省略できる、
// 引数の型は リストの型から推論できるので省略できる
list.forEach( (str) -> {System.out.println(str);} );
// 引数がひとつなら、引数の () を省略できる
list.forEach( str -> {System.out.println(str);} );
// 処理がひとつ(式のみ)なら、 処理の {} を省略できる
list.forEach( str -> System.out.println(str) );
ちなみに戻り値を返すときは
(str) -> { return str + "***"; };
// 処理がひとつ(式のみ)なら、{} と return を省略できる
(str) -> str + "***";
どのような仕組みでこのように記述できるのかを理解する
関数型インタフェース
関数型インタフェースとは、「抽象メソッドを一つだけ持つインタフェース」のこと。
interface MyMath {
int operate(int a, int b); //何かしらの計算をして結果を返す抽象メソッド
}
この一つの抽象メソッドを実装する必要があるわけだが、そこでラムダ式を使う。
(インタフェースを実装した各クラスを作成してそのインスタンスを生成する、という方法より効率的である)
関数型オブジェクト
ラムダ式によって関数型オブジェクト生成し、その関数型オブジェクトを変数に代入して使うことができる。
MyMath add = (a, b) -> a + b;
MyMath mult = (a, b) -> a * b;
変数addやmultには、MyMathインタフェースを実装したクラスから生成したインスタンスが代入されている。インタフェースを実装するとは、抽象メソッドをオーバーライドするということであるが、そのオーバーライドを行っているのがこの右辺の部分である。
上のコードは以下のコードと同じことである。
// 匿名クラスをその場で作成して、そのインスタンスを生成する
MyMath add = new MyMath() {
@Override
public int operate(int a, int b) {
return a + b;
}
};
MyMath mult = new MyMath() {
@Override
public int operate(int a, int b) {
return a * b;
}
};
つまり、ラムダ式で何ができるのかというと
- 関数型インタフェースを実装したクラスを即席で作成する
- そのクラスのインスタンスを生成する
- そのインスタンスは変数に代入したり、引数として渡すことができる
System.out.println(add.operate(3, 5)); // 8
System.out.println(mult.operate(3, 5)); // 15
Javaが用意している関数型インタフェース
関数型インタフェースを自作しなくてもJavaには複数の関数型インタフェースが用意されていて、引数や戻り値の有無で使い分ける。
インターフェース名 | メソッドの形 | 意味 |
---|---|---|
Consumer | void accept(T t) | 値を受け取り、返さない処理 |
Supplier | T get() | 値を返すが、引数は受け取らない |
Function | R apply(T t) | 値を受け取って、別の値を返す |
Predicate | boolean test(T t) | 値を受け取り、true/false を返す |
BiConsumer | void accept(T t, U u) | 2つの引数を受け取り、返さない処理 |