Java 9 Streamに追加された3つの新機能

# Java 9 Stream 新機能
　
　JDK9 build b83 (以下 Java 9) の Stream に追加された「全」3 個の新機能を使ってみました。

| 機能 | Java 8 | Java 9 (build b83) | JavaDoc |
|-----|------|-------|-------|
| 条件を満たす間のデータを対象外とする | n/a | [dropWhile](#dropwhile) | [Stream<T> dropWhile(Predicate<? super T> predicate)](http://download.java.net/java/jigsaw/docs/api/java/util/stream/Stream.html#dropWhile-java.util.function.Predicate-) |
| 条件を満たす間のデータを対象とする | n/a | [takeWhile](#takewhile) | [Stream<T> takeWhile(Predicate<? super T> predicate)](http://download.java.net/java/jigsaw/docs/api/java/util/stream/Stream.html#takeWhile-java.util.function.Predicate-) |
| Null 許容 | n/a | [ofNullable](#ofnullable) | [static <T> Stream<T> ofNullable(T t)](http://download.java.net/java/jigsaw/docs/api/java/util/stream/Stream.html#ofNullable-T-) |


## dropWhile

### メリット
　Java 8 では，リストの先頭から条件を満たす間のデータを対象外にしたい場合はデータをスキップさせる泥臭い処理が必要でした。

　Java 9 では，対象外にしたいデータの条件を dropWhile に設定するだけで，対象外にしたいデータを簡単にスキップすることができるようになりました。

### Java 8

```java
// arrange
List<Integer> list = Arrays.asList(0, 1, 2, -1, 2);

// act
Predicate<Integer> p = (x) -> x <= 1;

boolean isDirty = false;
for (Integer x : list) {
    if (!isDirty && p.negate().test(x)) isDirty = true;
    if (isDirty) System.out.println(x);
}
// 2
// -1
// 2

long skipIndex = list.indexOf(list.stream().filter(p.negate()).findFirst().get());
list.stream().skip(skipIndex).forEach(System.out::println);
// 2
// -1
// 2
```

### Java 9

```java
// arrange
List<Integer> list = Arrays.asList(0, 1, 2, -1, 2);

// act
list.stream().dropWhile(x -> x <= 1).forEach(System.out::println);
// 2
// -1
// 2
```

### 他の言語

| 言語 | Java 9 dropWhile |
|-----|------|
| Haskell | [dropWhile](http://www.cse.unsw.edu.au/~en1000/haskell/inbuilt.html#takeWhile) |
| Scala | [dropWhile](http://www.scala-lang.org/api/current/index.html#scala.collection.Iterable@dropWhile(p:A=>Boolean):Repr) |
| Python| [dropWhile](https://docs.python.org/2/library/itertools.html#itertools.dropwhile) |
| Ruby | [drop_while](http://ruby-doc.org/core-2.2.3/Enumerator/Lazy.html#method-i-drop_while) |
| C# | [SkipWhile](https://msdn.microsoft.com/en-us/library/bb549075(v=vs.110).aspx) |


## takeWhile

### メリット

　Java 8 では，リストの先頭から条件を満たす間のデータを対象にしたい場合，条件を満たさないデータをスキップする処理が必要でした。

　Java 9 では，対象にしたいデータの条件を takeWhile に設定するだけで，必要なデータを簡単に処理できるようになりました。

### Java 8

```java
// arrange
List<Integer> list = Arrays.asList(0, 1, 2, -1, 2);

// act
for (Integer x : list) {
    if (x <= 1) System.out.println(x);
    else break;
}
// 0
// 1
```

### Java 9

```Java
// arrange
List<Integer> list = Arrays.asList(0, 1, 2, -1, 2);

// act
list.stream().takeWhile(x -> x <= 1).forEach(System.out::println);
// 0
// 1
```

### 他の言語

| 言語 | Java 9 takeWhile|
|-----|------|
| Haskell | [takeWhile](http://www.cse.unsw.edu.au/~en1000/haskell/inbuilt.html#takeWhile) |
| Scala | [takeWhile](http://www.scala-lang.org/api/current/index.html#scala.collection.Iterable@takeWhile(p:A=>Boolean):Repr) |
| Python| [takeWhile](https://docs.python.org/2/library/itertools.html#itertools.takewhile) |
| Ruby | [take_while](http://ruby-doc.org/core-2.2.3/Enumerator/Lazy.html#method-i-take_while) |
| C# | [TakeWhile](https://msdn.microsoft.com/en-us/library/bb548775(v=vs.100).aspx) |


## ofNullable

### メリット

　Java 8 では，以下のコードのような場合に null 判定が必要でした。

　Java 9 では，null を含む可能性がある処理に ofNullable を適用することで，null 判定が不要となりました。

### Java 8

```java
// arrange
List<String> list = Arrays.asList("Angular", "ES7", "React");
Map<String, Integer> map = new HashMap<String, Integer>() {
    {
        put("Angular", 1);
        put("ES2016", 2);
        put("React", 3);
    }
};

// act
list.stream().flatMap(str -> {
    Integer temp = map.get(str);
    return (temp != null) ? Stream.of(temp) : Stream.empty();
}).forEach(System.out::println);
// 1
// 3
```

### Java 9

```java
// arrange
List<String> list = Arrays.asList("Angular", "ES7", "React");
Map<String, Integer> map = new HashMap<String, Integer>() {
    {
        put("Angular", 1);
        put("ES2016", 2);
        put("React", 3);
    }
};

// act
list.stream().flatMap(str -> Stream.ofNullable(map.get(str))).forEach(System.out::println);
// 1
// 3
```

# 結論
　
　Java 9 (JDK9 build b83) Stream に追加された機能は僅か3つです。（2015/10/22現在）
　Stream は進化を止めたのでしょうか？
　Stream にはまだまだ必要な機能があります。
　zip，intersect（積集合），union（和集合），except（差集合）など…
　
　
　
　
　
　
 
　…僕の [jLinqer](http://qiita.com/k--kato/items/ec7ab8b392fa8bb0a732) にはzip も intersect もあります　(/ω・＼)ﾁﾗｯ

# 付録

## Java 9 環境構築

| # | 手順 | 操作 | 図　|
|-----|-----|-----|-----|
1 | JDK9 をダウンロード | [JDK 9 Early Access with Project Jigsaw, build b83](https://jdk9.java.net/jigsaw/) | ![jdk9_download.png](https://qiita-image-store.s3.amazonaws.com/0/67778/e3266dc0-e709-3b37-2f09-072cc34499a1.png) |
2 | IntelliJ をダウンロード | [IntelliJ IDEA Community Edition](https://www.jetbrains.com/idea/download/) | ![intellij_download.png](https://qiita-image-store.s3.amazonaws.com/0/67778/c3bc250f-00b7-600b-4d76-300473d366f3.png) |
3 | IntelliJ SDK 設定 1 | File > Project Structure > SDKs > + > JDK > "JDK9を解凍したフォルダ" を選択 | ![intellij_sdk1.png](https://qiita-image-store.s3.amazonaws.com/0/67778/7c484c84-6ee8-2362-e56f-643c65e09c46.png) |
4 | IntelliJ SDK 設定 2 | File > Project Structure > Project > Project SDK > "1.9" を選択 | ![intellij_sdk2-3.png](https://qiita-image-store.s3.amazonaws.com/0/67778/8ff09766-5477-568d-739a-eacfc0e67225.png) |
5 | IntelliJ SDK 設定 3 | File > Project Structure > Project > Project Language Level > ~~"9 - JDK modularization etc."~~ `X - Experimental features` を選択 |  |
6 | IntelliJ SDK 設定 4 | File > Project Structure > Project > Modules > Sources > ~~"9 - JDK modularization etc."~~ `X - Experimental features` を選択 | ![intellij_sdk4.png](https://qiita-image-store.s3.amazonaws.com/0/67778/c5daba49-81bd-2d15-64d4-eb459e618d8a.png) |

## Java 9 Stream ソースコード サンプル
　
　GitHub にサンプルをアップしました。
　　GitHub, j9Stream, https://github.com/k--kato/j9Stream

## IntelliJ Java 9 のコンパイルエラー
　
　~~以下の IntelliJ コンパイルエラーは未解決です。
　Maven を使って compile & test を実施しています。~~

```java
Error:Abnormal build process termination: 
エラー: メイン・クラスorg.jetbrains.jps.cmdline.Launcherが見つからなかったかロードできませんでした
```

```java
Error:java: invalid flag: -release
```

　`X - Experimental features` を選択するとコンパイルが可能となります。

# 参考文献
[1] Java8, "Interface Stream<T>", http://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html
[2] Java9, "Interface Stream<T>", http://download.java.net/java/jigsaw/docs/api/java/util/stream/Stream.html
[3] Java.net JDK 9 Project, "JDK 9 Early Access with Project Jigsaw, build b83", https://jdk9.java.net/jigsaw/
[4] Paul Sandoz, "JDK Bug System JDK-8050819 Please add java.util.Stream.ofNullable(T object)", https://bugs.openjdk.java.net/browse/JDK-8050819
[5] guava-libraries, "Guava: Google Core Libraries for Java 1.6+", https://code.google.com/p/guava-libraries/issues/detail?id=619
[6] Stackoverflow, "How to start a new JavaFX project with JDK 9 in IntelliJ", http://stackoverflow.com/questions/39458945/how-to-start-a-new-javafx-project-with-jdk-9-in-intellij