Java8の新機能に関するメモ

# はじめに
ベースはこの辺の情報です。
http://www.techempower.com/blog/2013/03/26/everything-about-java-8/
http://www.infoq.com/jp/news/2013/09/everything-about-java-8
http://yoshio3.com/2014/03/21/congrats-javase8-launch/

- - - 
# インターフェースの仕様変更
* デフォルトメソッドが定義できるようになった
 * mixin(RubyでいうModuleみたいなの)が可能に
 * http://equj65.net/tech/java8mixin/

```java:Iterable#forEach
    default void forEach(Consumer<? super T> action) {
        Objects.requireNonNull(action);
        for (T t : this) {
            action.accept(t);
        }
    }
```
* staticメソッドが定義できるようになった

# ラムダ式
## 概要
Java7までは関数をオブジェクトとして渡せなかったので、関数型っぽい書き方をしたい場合は関数をインターフェースとして定義し無名クラスのインスタンスを生成する必要があった。

```java
Collections.sort(students, new Comparator<Student>() {
    @Override
    public int compare(Student o1, Student o2) {
        return Integer.compare(o1.getHeight(), o2.getHeight());
    }
});
```
Java8からはラムダ式を利用することで以下のように書く事が出来る

```java
Collections.sort(students, (o1, o2) -> Integer.compare(o1.getHeight(), o2.getHeight()));
```
## ラムダ式の定義方法
```java
// 基本の書き方: (引数) -> { (処理) }
(int x, int y) -> {
    return x + y;
};

// 引数の型は省略可能
(x, y) -> {
    return x + y;
};

// さらに1行処理の場合は{}とreturnも省略可能
(x, y) -> x + y;

// 引数が一つの場合は()が省略可能
name -> "Hello " + name;

```

## ラムダ式を変数に代入する
ラムダ式を変数に代入するためには、_関数型インターフェース_を作成する必要がある
### 関数型インターフェースとは？
メソッドが一つしか無いインターフェースのこと。
ただし、Objectのメソッド(equalsとかtoStringとか)、Java8からinterfaceに導入されているstaticメソッドやdefaultメソッドは無視されるのであっても良い

```java
/**
 * 数値の計算処理を行う
 */
public interface Operator {
    public int apply(int x, int y);
}

Operator plus     = (x, y) -> x + y;
Operator minus    = (x, y) -> x - y;
Operator multiply = (x, y) -> x * y;
Operator divide   = (x, y) -> x / y;
```

## @FunctionalInterface
@FunctionalInterfaceをインターフェースに付けるとコンパイル時に関数型インターフェースの条件を満たすかどうかをチェックしてコンパイルエラーにしてくれる(無くても関数型インターフェースとして利用する事はできる)。関数型の利用を想定しているインターフェースはこのアノテーションを付けるのが良い。

## 標準APIで用意されている関数型インターフェース
+ Function<T, R> - Tを入力として取り，Rを出力として返す
+ Predicate<T> - Tを入力として取り，論理型(boolean)を出力として返す
+ Consumer<T> - Tを入力として取り，何も返さない
+ Supplier<T> - 入力を取らず，Tを返す
+ BinaryOperator<T> - ２つのTを入力として取り，１つのTを出力として返す

その他にもあります、詳しくは以下を参照
http://www.ne.jp/asahi/hishidama/home/tech/java/functionalinterface.html#h_API

## メソッド参照
既存のメソッドを(::)で呼び出すことでラムダ式化が出来る。
既存のメソッドをラムダ式にするための簡略形。

```java
List<String> list = Arrays.asList("a", "b", "c", "d");
list.forEach(System.out::println);
//list.forEach((str) -> {
//    System.out.println(str);
//});
```

# Stream
## 概要
集合体を表すインターフェースで、集合に対する処理を簡潔に記述する事が可能になった

```java
// Java7
int sum = 0;
for (int i = 1; i < 101; i++) {
    sum += i;
}

// Java8
int sum = IntStream.range(1, 101).sum();
```
もうちょい複雑な処理(Mapreduce)だとこんな感じ

```java
Path path = FileSystems.getDefault().getPath("./src/main/java/wordcount.txt");

Files.lines(path)
        // Map
        .flatMap(line -> Arrays.stream(line.split("( |\\.|,)+")))
        // Reduce
        .collect(Collectors.groupingBy(word -> word, Collectors.counting()))
        // Output
        .forEach((k, v) -> System.out.println(k + ":" + v));

```
* http://qiita.com/tfunato/items/a5744cec202af64573a5 を参考
* Java7までだとファイルを読んで1行ごとに分割してfor文で回して結果をMapに詰めて・・・
 * Java6までだとリソースのクローズ処理も必要・・・

## streamの並列実行

マルチスレッドでストリームを処理する場合はStream#parallelsを呼ぶだけでOK
基本的にストリーム処理は隠蔽されてるので、Javaのバージョンアップをするだけでパフォーマンス改善する可能性がある。

```java
Path path = FileSystems.getDefault().getPath("./src/main/java/wordcount.txt");

Files.lines(path)
        // Map
        .flatMap(line -> Arrays.stream(line.split("( |\\.|,)+")))
        // Concurrent
        .parallel()
        // Reduce
        .collect(Collectors.groupingBy(word -> word, Collectors.counting()))
        // Output
        .forEach((k, v) -> System.out.println(k + ":" + v));

```

# 日付API
使いづらいのは相変わらずだけど高機能にはなっているらしい・・・
http://d.hatena.ne.jp/nowokay/20130917

# Nashorn JavaScript エンジン
https://blogs.oracle.com/wlc/entry/javaee_c117
http://orablogs-jp.blogspot.jp/2014/03/oracle-nashorn-next-generation.html

元々JavaにはJavaScript実行エンジン(Rhino)があったが、invokeDynamicなどを使ってパフォーマンスが向上したエンジン(Nashorn)に置き換わった。

* ECMAScript-262 Edition 5.1準拠
* ナスホーンと読むらしい

## JavaでJavaScriptを呼び出す
```java
ScriptEngineManager engineManager = new ScriptEngineManager();
ScriptEngine engine =
        engineManager.getEngineByName("nashorn");
engine.eval("function sum(a, b) { return a + b; }");
System.out.println(engine.eval("sum(1, 2);"));
```
## JavaScriptからJavaを呼び出す
```js
var list = java.util.Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8);
var odd = list.stream().filter(function(i) {
  return i % 2 == 0;
});
odd.forEach(function(i) {
  print(">>> " + i);
}); 
```
http://qiita.com/kamatama_41/items/82fb16a1f81c2996c12c

# パフォーマンス
Java7とJava8を同一構成で比較して12から41パーセント性能が向上しているという結果も。
http://japanmediacentre.oracle.com/content/detail.aspx?ReleaseID=3195&NewsAreaId=2

# Webフレームワーク
## Spring
* Spring4.0からJava8対応
* http://d.hatena.ne.jp/tatsu-no-toshigo/20140116/1389886428

## Play
* Play2.3から対応
* http://www.infoq.com/jp/news/2014/06/play-23

## Spark
* 今はやりの軽量フレームワーク、RubyのSinatraインスパイアらしい
* spark2.0.0からラムダ式が使える
* http://www.sparkjava.com/

# ThoughtWorksに認められたJava8
ThoughtWorks Technology RadarでJava8がいきなりAdaptになりました。(2014 July)
http://www.thoughtworks.com/radar/languages-and-frameworks/java-8

> The team behind Java 8 had to fight two battles: the community forces encouraging forever backwards compatibility (a long hallmark of Java) and the technical challenge of making a deep language change mesh with existing libraries and features. They succeeded on both fronts, breathing new life into the Java Language and placing it on par with other mainstream languages in terms of functional programming features. In particular, Java 8 has excellent syntactic magic that allows seamless interoperability between Lambda blocks, the new higher-order function feature, and SAM (Single Abstract Method) interfaces, the traditional way of passing behavior.

Java8は素晴らしい構文の魔法で他のメジャーな関数型プログラミング機能をもつ言語と同等、かつシームレスな後方互換性を手に入れることに成功した、的なことが書いてある(と思う)