ラムダとPredicate

このレッスンを終えると、ラムダ式の書き方として正しいものを見分け、Predicate と removeIf の組み合わせを追えるようになります。

まず予測してください

次のうち、コンパイルが通るのはどれでしょうか。

Predicate<Integer> a = n -> n > 10; Predicate<Integer> b = (n) -> { return n > 10; }; Predicate<Integer> c = (Integer n) -> n > 10; Predicate<Integer> d = n -> { n > 10; }; Predicate<Integer> e = (int n) -> n > 10;

通るのは a と b と c です。d と e が落ちます。

ラムダ式の形の規則

引数が1つのときだけ、かっこを省けます。0個や2個以上のときは省けません。型を書くなら全部の引数に書くか、全部書かないかのどちらかです。片方だけ型を書くと落ちます。

本体を波かっこで囲んだときは、値を返す関数型インターフェースなら return が要ります。d は n > 10; と書いただけで返していないので落ちます。逆に波かっこを使わない式の形では return を書けません。

e が落ちるのは、Predicate<Integer> の引数の型が Integer であって int ではないからです。型を明示するなら宣言どおりの型にします。

関数型インターフェースは抽象メソッドが1つ

ラムダ式を代入できるのは、抽象メソッドがちょうど1つのインターフェースだけです。Predicate<T> が持つ抽象メソッドは boolean test(T t) の1つだけなので、ラムダ式をそのまま代入できます。default メソッドや static メソッドはいくつ持っていても構いません。抽象メソッドを2つ持つインターフェースにラムダを代入させて落とす問題が出ます。

and と or と negate と removeIf

Predicateandornegate を持っています。これらは新しい Predicate を返すだけで、元の Predicate は変わりません。p.negate() を呼んでも p の判定はそのままです。

removeIf は、条件が true になった要素を List から取り除きます。「残す」ではなく「消す」であることを取り違えさせる出題が定番です。

もう1つの注意点として、ラムダの中から使えるローカル変数は実質的に final なものだけです。あとから代入し直している変数をラムダの中で読むと、コンパイルエラーになります。

要件

  1. 10, 20, 30, 40, 50, 60 をこの順に List へ入れる
  2. limit より大きいかを判定する Predicate と、20 で割り切れるかを判定する Predicate を作る
  3. その2つを and でつないだ条件で removeIf する
  4. 残った List の toString と、1つ目の Predicate を negate したもので 60 を判定した結果を、スラッシュでつないで返す

入出力例

filter(30)"[10, 20, 30, 50]/false" filter(100)"[10, 20, 30, 40, 50, 60]/true" filter(25)"[10, 20, 30, 50]/false"

ヒント

生田 陸人
ゆめさくエンジニア / 現役ソフトウェアエンジニア
編集 LuaGate編集部
main.java
学習モード

メモ

ラムダとPredicate

⌘S で保存