【JavaGold SE8】ラムダ式とは何ぞや

## はじめに
**ラムダ式**って初見だと読めない独特なスタイルですよね。
ちょっと整理してみます。

## 1.ラムダ式の基本形
こんなやつ
```java
Runnable r = () -> System.out.println("OK");
// (引数リスト) -> メソッドの実装

// 引数ありバージョン
Consumer<String> consumer = (str) -> System.out.println(str);

// 戻り値ありバージョン
Supplier<String> supplier = () -> {return "OK"};
```

## 2.なんのため？
匿名クラスの実装を簡潔に記述するために利用する。

#### ちょい脱線 「匿名クラス（無名クラス）」とは何か
まず、ローカルクラスというメソッドの処理中にクラスを宣言して利用できる仕組みがある。
##### ローカルクラス
```java
public static void main(String[] args) {

  class Local implements Runnable { // メソッド内でクラスを宣言(Runnableインタフェースを継承)
    @Override
    public void run() { // Runnableインタフェースのrunメソッドをオーバーライド
      System.out.println("OK");
    }
  }

  Runnable r = new Local(); // 宣言したローカルクラスをnewして利用する
  r.run(); // 「OK」が出力される
}
```
そのローカルクラスの「宣言からnewして利用するまで」の流れのうち、宣言部分を省略して記述するのが匿名クラス
##### 匿名クラス
```java
public static void main(String[] args) {

  Runnable r = new Local() { // クラスの宣言を省略し、直接new(利用)する
    @Override
    public void run() { // Runnableインタフェースのrunメソッドをオーバーライド
      System.out.println("OK");
    }
  }

  r.run(); // 「OK」が出力される
}
```
匿名クラスをさらに省略したのがラムダ式
##### ラムダ式
```java
public static void main(String[] args) {

  Runnable r = () -> { System.out.println("OK"); };
  r.run(); // 「OK」が出力される
}
```

## 3.ラムダ式の利用条件
ラムダ式で使用できるのは**抽象メソッドが一つのインターフェースのみ**
以下のメソッド宣言の部分を省略しているため、インタフェースに抽象メソッドが複数あるとどれをオーバーライドしているのかがわからなくなる
```java
@Override
    public void run() {
```
SE8から新しくjava.util.functionパッケージ以下に単一のメソッドをもつインターフェース群が追加されており、これらは**関数型インタフェース**と呼ばれ、ラムダ式で利用できる。
関数型インタフェースについてはまた別の機会に。。。

## 4.匿名クラス〜ラムダ式になるまでをもう少し詳しく
**匿名クラス**
```java
public static void main(String[] args) {

  Runnable r = new Local() { // クラスの宣言を省略し、直接newする
    public void run() { // Runnableインタフェースのrunメソッドをオーバーライド
      System.out.println("OK");
    }
  };

  r.run(); // 「OK」が出力される
}
```
**ラムダ式への変換①**
```java
public static void main(String[] args) {

    Runnable r = //(new Local() {)  型推論により省略
        public void run() {
            System.out.println("OK");
        }
    //}

    r.run(); // 「OK」が出力される
}
```
**ラムダ式への変換②**
```java
public static void main(String[] args) {

    Runnable r = //(new Local() {) 型推論により省略
    // (public void run() {) 抽象メソッドは１つしかないため、どのメソッドかは自明であり省略
            System.out.println("OK");
     // }
// }

    r.run(); // 「OK」が出力される
}
```

**ラムダ式への変換③**

残った部分をぎゅっと集めて
```java
public static void main(String[] args) {

    Runnable r = System.out.println("OK");

    r.run(); // 「OK」が出力される
}
```
↓↓↓　ラムダ式の書き方を適用
```java
public static void main(String[] args) {

    Runnable r = () -> System.out.println("OK"); 
    // アロー演算子「->」をつけて、中カッコ「{}」をとる。（returnが必要ない場合は中カッコを取る必要がある。）

    r.run(); // 「OK」が出力される
}
```

## 5.ラムダ式の「()」や「{}」の省略事情
1. 引数リストの省略

引数が1つの場合、カッコを省略することができる。
```Java
// 省略前
(String s) -> {
    System.out.println(s);
}

// 省略後
s -> {
    System.out.println(s);
}
```
2. ブロックの省略

戻り値の型がメソッド引数の型と一致し、かつ、処理が1行のみの場合、ブロックとreturnキーワードを省略することができる。
```Java
// 省略前
(String s) -> {
    return s.toUpperCase();
};

// 省略後
s -> s.toUpperCase();
```
3. 型注釈の省略

関数型インターフェースの型注釈が明らかであれば、型注釈を省略することができる。
```Java
// 省略前
Comparator<String> comparator = (String s1, String s2) -> s1.compareTo(s2);

// 省略後
Comparator<String> comparator = (s1, s2) -> s1.compareTo(s2);
```

## 結論
ラムダ式は慣れないと可読性が絶望的
でも使えるとつよつよ感が出て気持ちいい。