Java8のLambda, Stream, LocalDateについて

# 目的
 Lambda、Stream、LocalDateの使い方をマスターして普段から使えるようになろう！

# Lambda
#### Lambdaとは？
Lambdaはメソッドを変数として定義して使用する方法です。
Lambdaを使うとコード行を少なく記述することができます。
また、定義したメソッドを他のメソッドの引数に渡すこともできます。
数回しか使わなく他のクラスから参照しないメソッドはLambdaで書くようにしましょう！

#### 基本的な書き方
Lambdaはオーバーライドする関数名などを全て省略して書くため、メソッドが1つしか定義されていないインターフェースを継承する必要があります。
Javaにはすでに引数や戻り値の数に応じて使える関数型インターフェースを用意してくれているのでそれらを使います。

**※注意　引数と戻り値にintやdoubleといったプリミティブ型を使用するときはそれぞれ対応しているインターフェースを使いましょう！ （パフォーマンスに差が出てくるので）**
例)
// intを送ってintを受け取りたい時
Function  →  IntUnaryOperator

インターフェースの詳しい種類は以下に載っています。
http://www.ne.jp/asahi/hishidama/home/tech/java/functionalinterface.html#h_Function

#### 引数戻り値あり、Function
引数の型、戻り値の型というように定義します。
実行は`apply()`メソッドを使います。
2つの引数を受け取れるBiFunctionというものもあります。
引数と戻り値にint型を指定したい場合はFunctionではなく`IntUnaryOperator`を使います。
実行メソッドは`applyAsInt()`です。

```java

import java.util.function.*;

// main内
Function<String, String> f = (i) -> { return i +"OK"; };
System.out.println(f.apply("test"));  // testOK
```
#### 引数のみあり、Consumer
引数の型を指定します。
実行は`accept()`メソッドを使います。
引数をint型に指定したい場合は`IntConsumer`を使います。

```java
import java.util.function.*;

// main内
Consumer<String> c = i -> { System.out.println(i); };
c.accept("testOK");  // testOK
```
#### 戻り値のみあり、Supplier
戻り値の型を指定します。
実行は`get()`メソッドを使います。
戻り値をint型に指定したい場合は`IntSupplier`を使います。
実行メソッドは`getAsInt()`です。

```java
import java.util.function.*;

// main内
Supplier<String> s = () -> { return "testOK"; };
System.out.println(s.get());  // testOK
```
#### 引数を受け取って真偽値を返す、Predicate
実行は`test()`メソッドを使います。
FunctionのBoolean指定とPredicateの違いは、FunctionではBooleanが返ってくるのに対し,Predicateではプリミティブ型であるbooleanが返ってきます。
引数をint型に指定したい場合は`IntPredicate`を使います。

```java
import java.util.function.*;

// main内
Predicate<String> p = (i) -> { return i.equals("AAA"); };
System.out.println(p.test("AAA"));  // true
```

# Stream
#### Streamとは
List型のfor分などを簡潔に書くことができます。
また、メソッドの引数にLambdaを使うことができます。
使うときは`java.util.stream`をインポートしてきます。

まず、普通のfor分を考えてみます。

```java
for(int i; i < 10; i++){
    System.out.println(i+"回目です")；
}
```
これをStreamで書くと

```java
IntStream.range(0, 10).forEach(i -> System.out.println(i+"回目です"));
```
となり簡潔になります。

また、ArrayListの要素に対してforを回したい場合、

```java
// 変数listに対して
list.stream().forEach(i -> [処理])
```
というように書くことができます。

#### 中間操作と終端操作
streamには各要素の変換などを行う中間操作メソッドと最終的に値を返したり格納したりする終端操作メソッドがあるます。
終端操作を行わないと変換などをした各要素は保存されないので注意してください。

中間操作は以下のようなものがあります。
`.skip(n)`  ...  最初のn個の要素を捨てる。
`.limit(n)`  ... 最初のn個のみ取り出す。
`.filter(i -> [条件])` ... 条件に合うものを取り出す。
`.distinct()`  ... 重複を取り除く。
`.sorted()`  ... 自然順序でソートする。カッコ内にソート規則を指定することも可能。
`.map(i -> [処理])`  ... 全ての要素に処理を行う。

終端操作は以下のようなものがあります。
`.forEach(i -> [処理])`  ... 出力する。
`.findFirst()`  ... 始めの要素を返す。
`.collect()` ... 結果を作成する。(引数によって処理が変わる。)
`.count()`  ... 要素数を返す。
`.allMach([条件]) .anyMach([条件]) . noneMach([条件])` ... マッチしているか判定する。

# LocalDate
#### LocalDateとは
日付の処理を行うクラスです。
今まで使っていたCalendarクラスよりも扱いやすくなりました。
`java.time.LocalDate`をインポートして使います。

以下でよく使う操作を上げていきます。

#### 現在の日付取得
`LocalDate date = LocalDate.now();`
#### 日付セット
2020-01-01をセット
`localDate date = LocalDate.of(2020, 1, 1);`
Calendarと違い、Monthを-1しなくていい！
#### 文字列から日付セット
java.time.format.DateTimeFormatterをインポートする。

`date = LocalDate.parse("20200101",DateTimeFormater.ofPattern("yyyyMMdd"));`
下でも可能
`date = LocalDate.parse("2020-01-01");`
#### 日付取得
年
`date.getYear();`
月
`date.getMonth();`
日
`date.getDayOfMonth();`
曜日
`date.getDayOfWeek();`
#### 加減算
+10日
`date.plusDays(10);`
-10日
`date.miusDays(10);`
+2年
`date.plusYears(2);`
#### 日付同士の差
java.time.temporal.ChronoUnitをインポートする。

日にちの差
`long  diff = ChronoUnit.DAYS.between(date1, date2);`

# 参考資料
Lambda
http://www.ne.jp/asahi/hishidama/home/tech/java/functionalinterface.html#h_Function
https://qiita.com/sano1202/items/64593e8e981e8d6439d3

Stream
http://www.ne.jp/asahi/hishidama/home/tech/java/stream.html
https://qiita.com/kumazo/items/0876c5b251ecc131c960
https://qiita.com/kumazo/items/104fa685da8705b8cfd8
https://qiita.com/kumazo/items/284098c530fceb05805c

LocalDate
https://blog.y-yuki.net/entry/2016/09/15/003000)
https://m-shige1979.hatenablog.com/entry/2017/03/10/080000