ITと創作でねこを飼いたい

プログラミングやITで勉強したこと、疑問をまとめます。

ラムダ式の整理(試験対策)

今回はJavaラムダ式の構文についてまとめたいと思います。
ラムダ式を使ってコードを書こうってよりは、Java SilverやGoldのための試験対策といった感じです!
しかし若干横道に逸れます(笑)

基本

まず前提として、「実装が必要なメソッドを一つだけもつインターフェース」を作成する必要があります。 このようなインターフェースは「関数型インターフェース」と呼ばれます。

例えば以下のような関数型インターフェースがあった場合

interface Func {
    void dosomething(String str);
}

文字列を出力するラムダ式

(String str) -> { System.out.println(str); };

と書くことができます。 ちなみに (肝要な部分ではないので読み飛ばして大丈夫です)

(String str) -> { System.out.println(name); };

なんてするとコンパイルエラーですが、

(String name) -> { System.out.println(name); };

はありです。(インターフェースの中の変数名と同じにする必要はない)

上記のラムダ式と呼ばれる構文は、関数型インターフェース型の変数に代入して利用します。
試験勉強だけしていると意外と抜け落ちてしまうのですが(斯く言う私がそうですが、、)
関数型インターフェースのメソッドを呼び出すことで初めて、ラムダ式で定義した処理が実行されます(少し考えてみたら当たり前ですね)
プログラムで書くとこんな感じ

       String out = "ABC";
        Func funcout= (String str) -> { System.out.println(str);};
        //ABCとコンソールに出力される
        funcout.dosomething(out);

個人的に、ラムダ式のすごいところの一つは、
柔軟にメソッドの処理を変えられることではないかと思っています。
例えば、

       String out = "ABC";
        Func funcout= (String str) -> { System.out.println(str);};
        //ABCとコンソールに出力される
        funcout.dosomething(out);
        
        Func funcadd = (String str) -> { System.out.println(str + "!");};
        //ABC!とコンソールに出力される
        funcadd.dosomething(out);
        //ABCとコンソールに出力される(dosomethingの処理は当然上書きされない)
        funcout.dosomething(out);

上記プログラムのFunc型のfuncoutとfuncaddではメソッドdosomethingの処理が異なります。
これをラムダ式を使わずに書こうとしたら、あるクラスでオーバーライドして、mainメソッドでそのクラスをインスタンス化して・・・といった一手間も二手前もかける必要があります。
これだけでもラムダ式なんかすごい!(実装できたらカッコよさそう)

ラムダ式の省略

さて、横道はこのへんで、、ここからは試験対策に戻ります。
試験ではよくラムダ式の省略形が正しいのか判断する問題が出てきます。一通り省略のルールをまとめてみましょう。

まずは基本の構文

  関数型インタフェースの型 変数名 = (引数) -> {処理};

ラムダ式の引数の宣言では()を省略することができます

  関数型インタフェースの型 変数名 = 引数 -> {処理};

引数のかっこを省略するのであれば、引数の型は記述してはいけません。
また引数が二つの場合は引数の()は省略することができません

コンパイルエラーのパターン

  //どちらもコンパイルエラー(関数インタフェースへの代入は省略)
  String str - > {System.out.println(str);};
  a, b - > {System.out.println(a + b);};

さらに、実行したい処理が1つしかないのであれば、{}を省略することができます。

  //「処理」が一つしかない場合
  関数型インタフェースの型 変数名 = (引数) -> 処理;

さらにややこしいことに戻り値が存在した場合
{}省略→returnキーワードは記述できない
{}あり→returnキーワードを記述しなければコンパイルエラー

省略できるけど「ただし」がいっぱいつきます。
試験では混乱しないように!

Java.util.Functionパッケージ

関数型インターフェースについてJava SE8から標準でいくつか用意されたものが存在しています。
関数型インターフェースと関数メソッドの組み合わせはよく出てくるので加えて書いておきます。
(Java Silverの場合はPredicateしか試験では出てきません)

Consumer
引数を受け取って処理をする。結果を戻さない、引数の「消費者」
関数メソッド→void accept(T)

Supplier
何も受け取らずに結果だけを戻す「供給者」
関数メソッド→T get()

Predicate
引数を受け取ってそれを評価する「断定」
関数メソッド→boolean test(T)

Functions<T, R>
引数を受け取って、指定された型 (R)の結果を戻す「処理」
関数メソッド→R apply(T)

Java SilverもJava Goldも試験料は高いですが、よかったら受けてみてください!!
(私もGold来月受けるつもりです!頑張ります)