絵で理解するリスト処理 - java8 stream / javaslang -

「java8 で stream やってみたけど慣れねー」とか「ちょっと難しいことしようとするとできねー」ってのを良く聞くのでまとめてみるよ。

型さえ把握すれば８割方わかった様なもんなので、それを絵にしてみるよ。

~~ちなみに、記事は長いけど最初の`[本編 -`って見出しの箇所まで読めば十分だ！~~

やっぱ冷静に考えると長すぎるので、分割した。

## [本編 - java8 stream]: filter, map, reduce
基本の３手を押さえよう。

`reduce`には馴染みがないかもしれないけど、Google が提唱した`MapReduce`モデルってので`map`とは一緒に語られるよ。-> [wiki](https://ja.wikipedia.org/wiki/MapReduce)

以下の例題を使って見て行くよ。

```java
/*
 * 以下の様なログがある
 * ラベル もしくは ラベル:millisec の形式で１行ずつ出力される
 *
 * millisec の総和を求めよ
 */
List<String> lines = Arrays.asList(
    "application-boot", "access-dispatch:10", "dispatched", "authentication:30", "database-access:45", "response-creation:15", "access-logging"
);
```

大事なのはとにかく型なので、Generics にビビらずにそこだけはしっかり確認していくよ。

それから、こんな絵が大量に出てくるよ。

<img width="720" alt="legend.png" src="https://qiita-image-store.s3.amazonaws.com/0/113398/c00daf83-a280-9567-b355-594b11dbc644.png">

`A -> B f`って書いてあるのは java のコードにすると`B f(a);`ってことで、`A`や`B`には`String`や`Optional<Integer>`などの具体型が入ります。つまり Generics のことです。

### filter
`filter`の定義はこう。

```java
Stream<T> filter(Predicate<? super T> predicate);
```

`Predicate<T>`は「引数が`T`で戻り値が`bool`」ってこと、`? super T`とかは今は忘れておっけー。

`Predicate<T>`の型表記を`T を bool にする`って捉えて、`(T -> bool)`って書いてみよう。
ついでに Generics も簡略化してしまおう。

```java
Stream<T> filter((T -> bool) f);
```

`filter`を使って`lines`を`:`のある行だけにするのは、こう書ける。

```java
lines.stream()
        .filter(line -> line.contains(":"))                  // ["access-dispatch:10", "authentication:30", "database-access:45", "response-creation:15"]
```

定義を`T -> bool`と書いてみると、実装の`line -> line.contains(":")`が同じ様に見える。
（このお題では、`T`は具体的には`String`ってこと）

絵に描くとこんな感じだろうか。

<img width="720" alt="filter.png" src="https://qiita-image-store.s3.amazonaws.com/0/113398/7b829ea7-5bd3-43ce-69ae-3cd3cb400f47.png">

`filter`は **型** は変わらなくて、**数** が変わる変換ってことだ。

### map
`map`の定義はこう。

```java
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
```

こっちも同じ様に簡略化すると、こうだ。

```java
Stream<R> map((T -> R) f);
```

`map`を使って`ラベル:millisec`の行を`Integer`にするのは、`filter`の続きにこう書ける。

```Java
lines.stream()
        .filter(line -> line.contains(":"))                  // ["access-dispatch:10", "authentication:30", "database-access:45", "response-creation:15"]
        .map(line -> Integer.valueOf(line.split(":")[1]))    // [10, 30, 45, 15]
```

ここも定義の`T -> R`と実装が同じ形をしている。
（このお題では、`R`は具体的には`Integer`ってことだから、`T -> R`が`String -> Integer`に見えていると良い感じ）

絵に描くとこんな感じだろうか。

<img width="720" alt="map.png" src="https://qiita-image-store.s3.amazonaws.com/0/113398/67299e52-5a4d-d015-d534-5c9439d2a399.png">

`map`は **数** は変わらなくて、 **型** が変わる変換ってことだ。

### reduce
`reduce`の定義は java8 stream には３つあるけど、今から使うのはこうだ。

```java
T reduce(T identity, BinaryOperator<T> accumulator);
```

`BinaryOperator<T>`は少し見慣れないけど、「引数が`T`を２つで戻り値も`T`」ってことだ。
これもビビらずに簡略化してみよう。

```java
T reduce(T t, ((T, T) -> T) f);
```

`reduce`は一般に「畳み込み」と言われていて、リストの先頭から順に結果を蓄積していく処理だ。

`reduce`を使って`Integer`の行を`Integer`の総和にするのは、`map`の続きにこう書ける。

```java
lines.stream()
        .filter(line -> line.contains(":"))                  // ["access-dispatch:10", "authentication:30", "database-access:45", "response-creation:15"]
        .map(line -> Integer.valueOf(line.split(":")[1]))    // [10, 30, 45, 15]
        .reduce(0, (acc, n) -> acc + n)                      // 100
```

定義に少し括弧が多いけど、`T, (T, T) -> T`と`0, (acc, n) -> ...`が同じ形をしているから少しはわかりやすいはず。

絵に描くとこんな感じだろうか。

<img width="720" alt="reduce with zero a.png" src="https://qiita-image-store.s3.amazonaws.com/0/113398/4267d77f-846e-c7f3-1185-f5b619cc675f.png">

`reduce`は **リストの要素** が **単一の結果** になる処理だ。

### まとめ
これでクリアー！

```
 * millisec の総和を求めよ
```

は

```java
// ( 再掲 )

lines.stream()
        .filter(line -> line.contains(":"))                  // ["access-dispatch:10", "authentication:30", "database-access:45", "response-creation:15"]
        .map(line -> Integer.valueOf(line.split(":")[1]))    // [10, 30, 45, 15]
        .reduce(0, (acc, n) -> acc + n)                      // 100
```

で解けた。

一応全体の絵を載せておく。

<img width="720" alt="resolve.png" src="https://qiita-image-store.s3.amazonaws.com/0/113398/5fd36f90-16f7-e2b0-d9ed-c8edf074a17c.png">

## おわり
ここから先の全てのおまけは以下の記事に分離した。

[絵で理解するリスト処理 - java8 stream / javaslang - のおまけ](https://qiita.com/suzuki-hoge/items/b095f218d9b3d7f1e48c)

スッキリ。