Javaのラムダ式

##ラムダ式とは
Java8で導入された記述方法です。
同じくJava8で導入されたStream API[^1]はラムダ式を使うことが前提とされているため、ラムダ式を学んでおくとメリットがありそうです。

[^1]: 配列やリストなどのコレクションを扱う為のもので、値の集計やデータを使った処理を分かりやすいコードで実装することができるAPI。

また、ラムダ式を使うと、「匿名クラスを使った関数型インターフェースの記述」を簡潔にできるというメリットもあります。


###ラムダ式の書き方
ラムダ式の基本的な書き方は以下のとおりです。

```
インターフェース名　オブジェクト名 = 引数（複数受け取れる） -> 処理;
```
コンパイラが型推論してくれるので、引数の型は指定する必要はありません。
~~引数が1つしかない時は、returnや引数を囲む（)、処理を書く{}等は要りません~~
**※訂正**
{ } と return を省略できるのは、{ } の中が return 〜 という1文だけの場合です。
引数の数は関係ありません。

###匿名クラスを使った実装
匿名（無名）クラスとは、インターフェースを実装したローカルクラスの、宣言部分を省略したものです。
ラムダ式を使えば、匿名クラスを使わずに簡潔にわかりやすく書くことができます。

たとえば以下のような匿名クラスがあったとします。

```main.java

interface InterfaceTest{
    // 抽象メソッド
    public String name(String name);
}
 
public class Main {
 
    public static void main(String[] args) {
 
        // 匿名クラスを使った書き方
        InterfaceTest greeting = new InterfaceTest() {
            // オーバーライド
            public String name(String name) {
                return "Hello " + name;
            }
        };
        System.out.println(greeting.name("momoji"));
    }
 
}
```

上記では、インターフェースのインスタンスを生成しているように見えますが、実際はインターフェースをもった、無名クラスのインスタンスを生成しています。

実行結果↓

```
Hello momoji
```

###ラムダ式での実装

これをラムダ式で書き換えてみます。

```main.java
interface InterfaceTest{
    // 抽象メソッド
    public String name(String name);
}
 
public class Main {
 
    public static void main(String[] args) {
 
        // ラムダ式を使った書き方
        InterfaceTest greeting = (name) -> {
            return "Hello " + name;
        };
        System.out.println(greeting.name("momoji"));
    }
 
}

```
{}の中にはgreetingメソッドで行う処理内容が書かれています。
短くなった上、何をしているかが分かりやすくなりました。また、引数の型指定をしなくてよくなりました。

実行結果↓

```
Hello momoji
```


##forEach文をラムダ式を使ってもっと短く書く

Javaにはfor-each文と同じ性質を持ったもので、拡張for文というものがあります。配列やリストの全ての要素に指定した処理を行うという性質を持ちます。

拡張for分の書き方

```
for (データ型 変数名: listや配列){
  処理;
  ...
}
```

リストの要素を全て順番に出力するには、拡張for文だと以下のように書きます。

```main.java
main.java
class Main {
    public static void main (String[] args) {

            List<String> list = new ArrayList<>();
            list.add("a");
            list.add("b");
            list.add("c");

            // 拡張for文
            for(String l : list) {
                System.out.println(l);
            }

        }
}

```
上記の例では、
①String型のリスト「list」を定義する
②addメソッドでlistに"a","b","c"の要素をひとつずつ詰めていく
③拡張for文を使ってlistの要素をひとつずつ出力していく。

ということをしています。

実行結果は以下のようになります。

```
a
b
c
```


これを、ラムダ式とforEach文を使うともっと短くすることができます。


```main.java
class Main {
    public static void main (String[] args) {
 
            List<String> list = new ArrayList<>();
            list.add("a");
            list.add("b");
            list.add("c");
            
            // 拡張for文
            // for(String l : list) {
            //  System.out.println(l);
            // }

            // ラムダ式を使ったforEach文
            list.forEach(l -> System.out.println(l));
            
        }
}

```
実行結果↓

```
a
b
c
```
3行使って書いていたところを、1行に収めることができました。
これを「メソッド参照」を使うともっと短くすることができます。

##メソッド参照とは
これもJava8から導入された記法になります。
メソッド参照とは、メソッドの引数としてメソッドを参照できる仕組みのことです。
定義済みのメソッドを引数なしで呼び出すことができます。

メソッド参照は以下のように書きます。

```
クラス名 :: メソッド名
```
クラス名の後に「::」、呼び出したいメソッド名を書きます。メソッド名に()は不要です。

さっそくラムダ式と組み合わせてみます。

```main.java
// メソッド参照を使ったラムダ式
list.forEach(System.out::println);
```

実行結果↓

```
a
b
c
```
ラムダ式とメソッド参照の合わせ技で、ずいぶん短く書けるようになりました。