初心者向けのJava 応用編： stream

ちなみに基本編はないです

##前提
Javaってあれでしょ
クラスとメソッド使えて
if文とfor文つかえたらなんとかなるやつでしょ


って人向け

##で？
べつに書き方を変えたから性能が上がるとかはそこまでないですけど(いやまぁありますけど)
あほみたいに{}をふくらませるとほら、ね
なんか見にくいでしょ

```見にくい.java
package dummy;

import java.util.ArrayList;
import java.util.List;

/**
 * 見にくいサンプル
 * 
 * @author わたし
 *
 */
public class Dummy {

	/**
	 * main関数
	 * 
	 * @param args 引数
	 */
	public static void main(String[] args) {
		run();
	}

	/**
	 * 見にくい処理
	 */
	public static void run() {
		// 文字列のListを宣言
		List<String> strList = new ArrayList<String>();
		// aをめっちゃいれる
		for (int i = 0; i < 100; i++) {
			strList.add("a");
		}
		// 文字列について
		for (String str : strList) {
			if (str.isEmpty()) {
				// 空文字
				System.out.println("はいってないよ");
			} else if (str.equals("a")) {
				// a
				System.out.println("aですよ");
			} else {
				// その他
				for (int l = 0; l < 100; l++) {
					System.out.println(str);
				}
			}
		}
	}
}
```
んね、見にくいでしょ
じゃあこれをすっきりさせましょう

```すまーと.java
package dummy;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.IntStream;

/**
 * 見にくいサンプル<br>
 * ->改変しました
 * <p>
 * 
 * @author わたし
 * @author われ
 *
 */
public class Dummy {

	/**
	 * main関数
	 * 
	 * @param args 引数
	 */
	public static void main(String[] args) {
		run();
	}

	/**
	 * 見にくい処理
	 * ->改変
	 */
	public static void run() {
		// 文字列のListを宣言
		List<String> strList = new ArrayList<String>();
		// aをめっちゃいれる
		IntStream.range(0, 100).forEach(i -> strList.add("a"));
		// 文字列について
		strList.forEach(Dummy::conditions);
	}

	/**
	 * 入力値によって出力を変化<br>
	 * 分岐条件
	 * <p>
	 * <ul>
	 * <li>空文字 -> "はいってないよ"
	 * <li>"a" -> "aですよ"
	 * <li>その他 -> 入力値をそのまま出力
	 * </ul>
	 * @param str 入力される文字列
	 */
	public static void conditions(String str) {
		if (str.isEmpty())
			System.out.println("はいってないよ");
		else if (str.equals("a"))
			System.out.println("aですよ");
		else
			IntStream.range(0, 100).forEach(i -> {System.out.println(str);});
	}
}
```

変えた点
・回数指定のfor文を1行に
・for文で大きくくくると見にくいので1行に
・中の条件分岐を別メソッドに

まぁデッドコードありまくりの分岐なので意味ないんですけど
こんなにif文つなげなくて、条件1つで良いよってことなら
こんな感じですかね

```わっほい.java
package dummy;

import java.util.Arrays;
import java.util.List;

public class Dummy {

	public static void main(String[] args) {
		run("a");
	}

	/**
	 * 入力された文字列に対して<br>
	 * <p>
	 * a,b,c,d,e,f,gの文字と一致した場合に<br>
	 * 後方にわっほいを付け加えて出力
	 * 
	 * @param str 検索条件
	 */
	public static void run(String str) {
		List<String> list = Arrays.asList("a", "b", "c", "d", "e", "f", "g");
		list.stream().filter(v -> v.equals(str)).map(v -> v + "わっほい").forEach(Dummy::echo);
	}

	/**
	 * 入力値をコンソールに出力する処理
	 * 
	 * @param obj 入力値
	 */
	public static void echo(Object obj) {
		System.out.println(obj);
	}
}
```
じゃまなんで上の方は省略。
echo関数も別に分ける必要ないですが

##なにが言いたいかっていうと

必殺streamってことです

`streamは対象のソースに対して
0個以上の中間操作 + 1つの終端操作`

を行うすんごいやつです

##kwsk
```これだ.java
package mk42;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.IntStream;

public class Stream {

	public static void main(String[] args) {
		run();
	}

	public static void run() {
		// instance Initializer
		List<String> list = new ArrayList<String>() {
			{
				// あえて改行しないとみやすかったりする
				IntStream.range(0, 100).forEach(i -> {add("a");});
			}
		};

		/** listというソースに対してstreamをつかうよ宣言 */
		list.stream();

		/** 中間操作(やらんでもいい) */
		// 要素に対して"a"を加える (valueの略でvとか変数つけてます、なんでもおｋ)
		list.stream().map(v -> v + "a");
		// 要素に対してフィルターをかけて、条件に合うやつだけかきあつめる
		list.stream().filter(v -> v.equals("a"));
		// 2重に中間操作もおｋ
		list.stream().filter(v -> v.equals("a")).map(v -> v + "a");

		/** 終端操作 */
		list.stream().forEach(v -> {
			// for文の中の処理
		});

		/** 最終形態 */
		list.stream().filter(v -> v.equals("a")).map(v -> v + "a").forEach(v -> {
			System.out.println(v);
		});
	}
}
```
ほいさ

```つまり.java
list.stream().filter(v -> v.equals("a")).map(v -> v + "a").forEach(v -> {
			System.out.println(v);
		});
```
`配列にstreamを使って→要素が"a"とequalsなものをかきあつめて→集めた要素に"a"を加えて→そいつらをsysoutする`
ってことです。これ1行。

中間操作と終端操作の種類はぐぐってください
[stream公式リファレンス](https://docs.oracle.com/javase/jp/8/docs/api/java/util/stream/Stream.html)


だいたい中間操作で基本的かつ便利なのは
・条件1つならif文の代わりになる`filter`
・要素を操作(足し算とかする)の`map`

終端操作はもっぱら`forEach`が便利です

インスタンスイニシャライザは完全にかっこつけました。大目に見てください。

ちなみに中間操作なしでforEachのみを使う場合はstreamなくても行けます

```適当★.java
list.forEach( v -> {sysout(v);};
```
みたいなね

##v -> v + 1 とかってなに！
ラムダ式って言うんでしたっけ、なんかわかりやすくて好きです
vはまじで適当につけてる変数なので、ほんとに何でもいい
一応valueの略称って名目だけど、かっこいいからv使ってるところある
streamちょうたのしい

##最後に
たのしいだけじゃなくて普通に可読性の高くなるものなので、
これはfor文の方が見やすいでしょって思うもの以外なら
是非streamをつかってみましょー！

全体的に、条件分岐が複雑だとstreamで1行じゃ対応しにくい、というか見ずらいので
分岐条件を別メソッドとして外出しするor素直にfor文つかうのがいいのかな

streamって名前がいいよね
綺麗

以上