徹底解説!project lambdaのすべて in fukuoka #j8fk

217
1 Project Lambdaのすべて 2014/6/14 14:10-15:00 福岡Java8勉強会 吉田 真也(@bitter_fox) I n F u k u o

Upload: bitterfox

Post on 15-Jan-2015

446 views

Category:

Technology


1 download

DESCRIPTION

福岡Java8勉強会で発表させていただいた時の資料です.

TRANSCRIPT

Page 1: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

1

徹底解説!Project Lambdaのすべて

2014/6/14 14:10-15:00

福岡Java8勉強会

吉田 真也(@bitter_fox) In Fukuoka

Page 2: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

2

Who are you?

● 吉田真也(@bitter_fox)● 職業: 学生

– 立命館大学 情報理工学部 情報システム学科

– 二回生

– 立命館コンピュータクラブ(RCC) 執行委員長(代表)● http://www.rcc.ritsumei.ac.jp/

Page 3: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

3

HashTag

#j8fk

Page 4: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

4

JavaSE8

Page 5: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

5

JavaSE8

Revolution

Page 6: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

6

JavaSE8

Revolution JavaSE5以来

(2004年)

Page 7: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

7

JavaSE8

Revolution JavaSE5以来

(2004年)

10年ぶ

Page 8: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

8

JavaSE8

Project Lambda

Revolution JavaSE5以来

(2004年)

10年ぶ

Page 9: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

9

Project Lambda

● 並列処理を容易に書ける様に増強– ライブラリ

– 言語

● StreamAPI(!=IOStream)の導入● ラムダ式の導入

Page 10: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

10

Why Project Lambda?

Page 11: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

11

マルチコアCPU

Page 12: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

12

マルチコアCPU

● CPU(ハード)のパラダイムシフト– クロック数はそのまま

コア(数)を増やす

– 並列処理

● ソフトウェアにもパラダイムシフト● 並列プログラミングにしないと性能をフルに利用で

きない– アムダールの法則

Page 13: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

13

アムダールの法則

90% 10%

90%

80% 20%

80%5%

1コア

1コア

∞コア

4コア

逐次処理 並列処理

Page 14: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

14

現代的なアーキテクチャ

少しでも多くの部分で並列処理

Page 15: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

15

並列処理ライブラリの歴史

java.lang.Thread扱いが難しかった/大きな粒度

JavaSE5(J2SE 5.0)

Concurrency Utilities(java.util.concurrent.*)簡単化/大きな粒度

JavaSE7

Fork/Join Framework小さな粒度/やや難

Page 16: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

16

ProjectLambda発足当時(JavaSE6〜JavaSE7)

小さな粒度向けのライブラリが無かった

JavaSE7後

小さな粒度向けのライブラリがあるものの使いづらい

Page 17: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

17

マルチコアCPUの台頭

マルチコアCPUコアライブラリ

Page 18: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

18

ライブラリでは不十分

new Runnable(){public void run(){

// proc}

}

● 処理を分けるだけで5行● いくらライブラリが良くても・・・● 言語的に解決する必要がある

Page 19: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

19

マルチコアCPUコアライブラリ

ラムダ式・メソッド参照

Page 20: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

20

マルチコアCPUコアライブラリ

ラムダ式・メソッド参照

実質的にfinal

型推論の強化

交差型キャスト

Page 21: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

21

ライブラリの増強

● 一度公開されたインターフェース– 変更を加えにくい

– メソッド追加

● 具象クラスが追随する必要がある– 実装の提供

Page 22: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

22

マルチコアCPUコアライブラリ

ラムダ式・メソッド参照

実質的にfinal

型推論の強化

交差型キャスト

defaultメソッド

Page 23: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

23

マルチコアCPUコアライブラリ

ラムダ式・メソッド参照

実質的にfinal

型推論の強化

交差型キャスト

defaultメソッド

stat. intf. メソッド

Page 24: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

24

マルチコアCPUコアライブラリ

ラムダ式・メソッド参照

実質的にfinal

型推論の強化

交差型キャスト

defaultメソッド

stat. intf. メソッド

ラムダ式・メソッド参照

Page 25: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

25

処理の分離のイディオム

new Runnable() {

public void run() {

//

}

}

Page 26: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

26

処理の分離のイディオム

new Runnable() {

public void run() {

//

}

}実装するべきメソッドが一つ

インターフェース

Page 27: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

27

● 実装するべきメソッド(抽象メソッド)が一つ● インターフェース

– java.lang.Runnable

– java.lang.Callable

– java.nio.file.PathMatcher

– java.awt.event.ActionListener

– java.swing.event.ChangeListner

– ...

Page 28: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

28

関数型インターフェース

● 実装するべきメソッド(抽象メソッド)が一つ● インターフェース

– java.lang.Runnable

– java.lang.Callable

– java.nio.file.PathMatcher

– java.awt.event.ActionListener

– java.swing.event.ChangeListner

– ...

Page 29: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

29

関数型インターフェース

● 処理を分けるのに十分● ライブラリの多くで利用されている

● 実装&インスタンス化する構文としてラムダ式– 匿名クラスに代わる構文

Page 30: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

30

関数型インターフェース?

interface F {

void f();

}

Page 31: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

31

関数型インターフェース?

interface F {

void f();

}

● Yes!

Page 32: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

32

関数型インターフェース?

interface F {

boolean equals(Object o);

}

Page 33: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

33

関数型インターフェース?

interface F {

boolean equals(Object o);

}

● No!

● equalsはObjectクラスで定義されている

– インターフェースにおいて暗黙的なメソッド

抽象メソッドは0個

Page 34: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

34

関数型インターフェース?

interface F {

Object clone();

}

Page 35: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

35

関数型インターフェース?

interface F {

Object clone();

}

● Yes!

● cloneもObjectクラスで宣言されているがprotected

– Fではpublicで再宣言されている

Page 36: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

36

関数型インターフェース(JLS9.8)A functional interface is an interface that has just one abstract method, and thus represents a single function contract. (In some cases, this "single" method may take the form of multiple abstract methods with override-equivalent signatures (8.4.2) inherited from superinterfaces; in this case, the inherited methods logically represent a single method.)

More precisely, for interface I, let M be the set of abstract methods that are members of I but that do not have the same signature as any public instance method of the class Object. Then I is a functional interface if there exists a method m in M for which the following conditions hold:

The signature of m is a subsignature (8.4.2) of every method's signature in M.

m is return-type-substitutable (8.4.5) for every method in M.

In addition to the usual process of creating an interface instance by declaring (8.1) and instantiating (15.9) a class, instances of functional interfaces can be created with lambda expressions (15.27), method references (15.28), or constructor references.

The function descriptor of a functional interface I is a method type (8.2) that can be used to legally override (8.4.8) the abstract method(s) of I.

Let M be the set of abstract methods defined above for I. The descriptor of I consists of the following:

Type parameters, formal parameters, and return types: Let m be a method in M with i) a signature that is a subsignature of every method's signature in M and ii) a return type that is a subtype of every method's return type in M (after adapting for any type parameters (8.4.4)); if no such method exists, then let m be a method in M that i) has a signature that is a subsignature of every method's signature in M and ii) is return-type-substitutable for every method in M. Then the descriptor's type parameters, formal parameter types, and return type are as given by m.

Thrown types: The descriptor's thrown types are derived from the throws clauses of the methods in M. If the descriptor is generic, these clauses are first adapted to the type parameters of the descriptor (8.4.4); if the descriptor is not generic but at least one method in M is, these clauses are first erased. Then the descriptor's thrown types include every type, E, satisfying the following constraints:

E is mentioned in one of the throws clauses.

For each throws clause, E is a subtype of some type named in that clause.

A functional interface type is one of the following:

A functional interface

A parameterization (4.5) of a functional interface

An intersection (4.9) of interface types that meets the following criteria:

Exactly one element of the intersection is a functional interface, or a parameterization of a functional interface. Let F be this interface.

A notional interface, I, that extends all the interfaces in the intersection would be a functional interface. If any of the intersection elements is a parameterized type, then I is generic: for each element of the intersection that is a parameterized type J<A1...An>, let P1...Pn be the type parameters of J; then P1...Pn are also type parameters of I, and I extends the type J<P1...Pn>.

The function descriptor of I is the same as the function descriptor of F.

The function descriptor of a parameterized functional interface, F<A1...An>, where A1...An are type arguments (4.5.1), is derived as follows. Let P1...Pn be the type parameters of F; types T1...Tn are derived from the type arguments according to the following rules (for 1 ≤ i ≤ n):

If Ai is a type, then Ti = Ai.

If Ai is a upper-bounded wildcard ? extends Ui, then Ti = Ui.

If Ai is a lower-bounded wildcard ? super Li, then Ti = Li.

If Ai is an unbound wildcard ?, then if Pi has upper bound Bi that mentions none of P1...Pn, then Ti = Bi; otherwise, Ti = Object.

If F<T1...Tn> is a well-formed type, then the descriptor of F<A1...An> is the result of applying substitution [P1:=T1, ..., Pn:=Tn] to the descriptor of interface F. Otherwise, the descriptor of F<A1...An> is undefined.

The function descriptor of an intersection that is a functional interface type is the same as the function descriptor of the functional interface or parameterization of a functional interface that is an element of the intersection.

Page 37: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

37

関数型インターフェース(JLS9.8)A functional interface is an interface that has just one abstract method, and thus represents a single function contract. (In some cases, this "single" method may take the form of multiple abstract methods with override-equivalent signatures (8.4.2) inherited from superinterfaces; in this case, the inherited methods logically represent a single method.)

More precisely, for interface I, let M be the set of abstract methods that are members of I but that do not have the same signature as any public instance method of the class Object. Then I is a functional interface if there exists a method m in M for which the following conditions hold:

The signature of m is a subsignature (8.4.2) of every method's signature in M.

m is return-type-substitutable (8.4.5) for every method in M.

In addition to the usual process of creating an interface instance by declaring (8.1) and instantiating (15.9) a class, instances of functional interfaces can be created with lambda expressions (15.27), method references (15.28), or constructor references.

The function descriptor of a functional interface I is a method type (8.2) that can be used to legally override (8.4.8) the abstract method(s) of I.

Let M be the set of abstract methods defined above for I. The descriptor of I consists of the following:

Type parameters, formal parameters, and return types: Let m be a method in M with i) a signature that is a subsignature of every method's signature in M and ii) a return type that is a subtype of every method's return type in M (after adapting for any type parameters (8.4.4)); if no such method exists, then let m be a method in M that i) has a signature that is a subsignature of every method's signature in M and ii) is return-type-substitutable for every method in M. Then the descriptor's type parameters, formal parameter types, and return type are as given by m.

Thrown types: The descriptor's thrown types are derived from the throws clauses of the methods in M. If the descriptor is generic, these clauses are first adapted to the type parameters of the descriptor (8.4.4); if the descriptor is not generic but at least one method in M is, these clauses are first erased. Then the descriptor's thrown types include every type, E, satisfying the following constraints:

E is mentioned in one of the throws clauses.

For each throws clause, E is a subtype of some type named in that clause.

A functional interface type is one of the following:

A functional interface

A parameterization (4.5) of a functional interface

An intersection (4.9) of interface types that meets the following criteria:

Exactly one element of the intersection is a functional interface, or a parameterization of a functional interface. Let F be this interface.

A notional interface, I, that extends all the interfaces in the intersection would be a functional interface. If any of the intersection elements is a parameterized type, then I is generic: for each element of the intersection that is a parameterized type J<A1...An>, let P1...Pn be the type parameters of J; then P1...Pn are also type parameters of I, and I extends the type J<P1...Pn>.

The function descriptor of I is the same as the function descriptor of F.

The function descriptor of a parameterized functional interface, F<A1...An>, where A1...An are type arguments (4.5.1), is derived as follows. Let P1...Pn be the type parameters of F; types T1...Tn are derived from the type arguments according to the following rules (for 1 ≤ i ≤ n):

If Ai is a type, then Ti = Ai.

If Ai is a upper-bounded wildcard ? extends Ui, then Ti = Ui.

If Ai is a lower-bounded wildcard ? super Li, then Ti = Li.

If Ai is an unbound wildcard ?, then if Pi has upper bound Bi that mentions none of P1...Pn, then Ti = Bi; otherwise, Ti = Object.

If F<T1...Tn> is a well-formed type, then the descriptor of F<A1...An> is the result of applying substitution [P1:=T1, ..., Pn:=Tn] to the descriptor of interface F. Otherwise, the descriptor of F<A1...An> is undefined.

The function descriptor of an intersection that is a functional interface type is the same as the function descriptor of the functional interface or parameterization of a functional interface that is an element of the intersection.

@FunctionalInterface

Page 38: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

38

@FunctionalInterface

● 関数型インターフェースかどうか検査する– コンパイル時

@FunctionalInterfaceinterface F { boolean equals(Object o);}

Page 39: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

39

@FunctionalInterface

● 関数型インターフェースかどうか検査する– コンパイル時

@FunctionalInterfaceinterface F { boolean equals(Object o);} @FunctionalInterface

^ Fは機能インタフェースではありません インタフェース Fで抽象メソッドが見つかりませんエラー1個

Page 40: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

40

java.util.function.*

名前 第一引数 第二引数 戻り値

Consumer<T> T - void

Function<T, R> T - R

Predicate<T> T - boolean

Supplier<T> - - T

BiConsumer<T, U> T U void

BiFunction<T, U, R> T U R

BiPredicate<T, R> T U boolean

Page 41: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

41

匿名クラスからラムダ式へ

this.addActionListener(

new ActionListener(){

public void actionPerformed(

ActionEvent ae) {

//

}

})

Page 42: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

42

匿名クラスからラムダ式へ

this.addActionListener(

new ActionListener(){

public void actionPerformed(

ActionEvent ae) {

//

}

})

addActionListenerの引数から推論できる

Page 43: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

43

匿名クラスからラムダ式へ

this.addActionListener(

new ActionListener(){

public void actionPerformed(

ActionEvent ae) {

//

}

})

実装するべきメソッドも一意に定まる

Page 44: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

44

ラムダ式

this.addActionListener(

(ActionEvent ae) -> {

//

})

● (仮引数) -> {メソッド本体}● (int n1, int n2) -> {return n1+n2;}

Page 45: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

45

ラムダ式

● 関数型インターフェースをインスタンス化

● (仮引数) -> {メソッド本体}– 型推論で型が決まる

● 関数型インターフェースのインスタンスが

予期される場面で利用可– ターゲット型

Page 46: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

46

ターゲット型が曖昧な場合

Object o = () -> {};

● () -> {}の型として

– Objectが予期される

– 関数型インターフェースが予期されない

– 何を実装したらいいのかわからない

Page 47: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

47

ターゲット型が曖昧な場合

Object o = (Runnable)() -> {};– キャストを用いる

– Runnableが予期される

– 実装するべきインターフェースが分かる

Page 48: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

48

ラムダ式の引数

this.addActionListener(

(ActionEvent ae) -> {

//

})

Page 49: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

49

ラムダ式の引数

this.addActionListener(

(ActionEvent ae) -> {

//

})

引数の型も一意に定まる

Page 50: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

50

ラムダ式の引数

this.addActionListener(

(ae) -> {

//

})

● 引数の型も省略可

● (n1, n2) -> {return n1+n2;}

Page 51: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

51

ラムダ式の引数

this.addActionListener(

(ae) -> {

//

})

引数が一つで型が推論される場合の()は不要

Page 52: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

52

ラムダ式の引数

this.addActionListener(

ae -> {

//

})

● 引数が一つで型が省略される場合()不要● n1 -> {return n1+5;}

Page 53: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

53

ラムダ式の引数と_

● ラムダ式の引数としての_はコンパイルエラー

this.addActionListener( _ -> {/**/} );– 他の言語での_は特殊な意味

– 混乱を招かないように利用不可に

– 将来の利用を見据え予約語に

● それ以外の_は警告に

Page 54: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

54

ラムダ式のメソッド本体

(int n) -> {return n + 5;}

(n) -> {return n + 5;}

n -> {return n + 5;}

Page 55: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

55

ラムダ式のメソッド本体

(int n) -> {return n + 5;}

(n) -> {return n + 5;}

n -> {return n + 5;}● return文のみ場合,return等を省略できる

(int n) -> n + 5

(n) -> n + 5

n -> n + 5

Page 56: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

56

ラムダ式のメソッド本体

(ActionEvent ae) -> {apply(ae);}

(ae) -> {apply(ae);}

ae -> {apply(ae);}

Page 57: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

57

ラムダ式のメソッド本体

(ActionEvent ae) -> {apply(ae);}

(ae) -> {apply(ae);}

ae -> {apply(ae);}● 戻り値がvoidでも,{;}を省略できる場合がある

(ActionEvent ae) -> apply(ae)

(ae) -> apply(ae)

ae -> apply(ae)

Page 58: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

58

ラムダ式.equals(匿名クラス)?

● 違います!– 匿名クラスのシンタックスシュガーではない

● 意味論も実装方法(OpenJDKの場合)も異なる– 主にスコーピング規則

– 同じ部分もある

Page 59: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

59

ラムダ式のスコーピング規則

1.ラムダ式内では外のスコープを引き継ぐ

2.常にアウタークラスのインスタンスを保持しない– 匿名クラスなどとは大きく違う

3.ローカル変数の参照はfinalな変数のみ– 匿名クラスと同様

– 注:実質的にfinal(後ほど説明)

Page 60: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

60

1.外のスコープを引き継ぐ

class Main {

void method() {

Runnable r = () ->

System.out.println(this);

}

}

Page 61: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

61

1.外のスコープを引き継ぐ

class Main {

void method() {

Runnable r = () ->

System.out.println(this);

}

}● ラムダ式内のthis=エンクロージングクラス

Page 62: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

62

1.外のスコープを引き継ぐ

class Main {

void method(int n) {

Runnable r = () -> {int n;};

}

}

Page 63: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

63

1.外のスコープを引き継ぐ

class Main {

void method(int n) {

Runnable r = () -> {int n;};

}

}● 多重定義

● コンパイルエラー

Page 64: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

64

1.外のスコープを引き継ぐ

class Main {

void method(int n) {

Function<Integer, Integer> f =

n -> n + 5;

}

}● 多重定義

● コンパイルエラー

Page 65: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

65

2.アウタークラスへの参照

● 匿名クラス– 常に保持

– メモリリークの危険性高

● ラムダ式– 必要に応じて保持

Page 66: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

66

2.アウタークラスへの参照

class Register {

void register(Processer p) {

p.add(new Func() {

public int f(int n) {return n * n;}

});

}

}

Page 67: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

67

2.アウタークラスへの参照

class Register {

void register(Processer p) {

p.add(new Func() {

public int f(int n) {return n * n;}

});

}

}

Registerのインスタンスへの参照が残るRegisterのインスタンスへの参照が残る

Page 68: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

68

2.アウタークラスへの参照

class Register {

void register(Processer p) {

p.add(n -> n * n);

}

}

Page 69: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

69

2.アウタークラスへの参照

class Register {

void register(Processer p) {

p.add(n -> n * n);

}

}Registerのインスタンスは保持しない

Page 70: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

70

3.ローカル変数の参照

● 匿名クラスと同様– finalな変数(実質的にfinal(後述)含む)– 値の変更不可

Page 71: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

71

ラムダ式の利用例

p -> p.getName()

s -> Integer.parseInt(s)

o -> list.add(o)

init -> new MyClass(init)

n -> new int[n]

● 引数を受け流すパターン

Page 72: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

72

ラムダ式の利用例

p -> p.getName()

s -> Integer.parseInt(s)

o -> list.add(o)

init -> new MyClass(init)

n -> new int[n]

● 引数を受け流すパターン● メソッド・コンストラクタ参照

Page 73: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

73

メソッド・コンストラクタ参照

p -> p.getName()

s -> Integer.parseInt(s)

o -> list.add(o)

init -> new MyClass(init)

n -> new int[n]

● クラス名等::メソッド or new

Person::getName

Integer::perseInt

list::add

MyClass::new

int[]::new

Page 74: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

74

マルチコアCPUコアライブラリ

ラムダ式・メソッド参照

実質的にfinal

型推論の強化

交差型キャスト

defaultメソッド

stat. intf. メソッド

Page 75: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

75

実質的にfinal(Effectively final)

● 匿名クラスやラムダ式で実質的にfinalな変数への参照が可能に– コンパイラがfinal性を推論

● 実質的にfinalな変数– final修飾されていない変数

– final修飾されてもエラーにならない変数

Page 76: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

76

実質的にfinalの例

void method(final int n) {

final String str = “HelloFinal”

Runnable r = new Runnable() {

public void run() {

System.out.println(str + n);

}};

}

Page 77: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

77

実質的にfinalの例

void method(int n) {

String str = “HelloEffectivelyFinal”

Runnable r = new Runnable() {

public void run() {

System.out.println(str + n);

}};

}

Page 78: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

78

実質的にfinalの例

void method(int n) {

String str = “HelloEffectivelyFinal”

Runnable r = () ->

System.out.println(str + n);

}

Page 79: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

79

実質的にfinalでない例

void method(int n) {

Runnable r = () ->

System.out.println(n);

n = 5;

}

ラムダ式から参照されるローカル変数は、finalまたは事実上のfinalである必要があります Runnable r = () -> System.out.println(n);

Page 80: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

80

実質的にfinalでない例

void method(int n) {

Runnable r = () -> n++;

}ラムダ式から参照されるローカル変数は、finalまたは事実上のfinalである必要があります Runnable r = () -> n++;

Page 81: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

81

マルチコアCPUコアライブラリ

ラムダ式・メソッド参照

実質的にfinal

型推論の強化

複合型キャスト

defaultメソッド

stat. intf. メソッド

Page 82: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

82

型推論の強化

● ターゲット型推論の強化

1.適用可能箇所の拡大

2.より正確な推論

Page 83: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

83

ターゲット型推論?

● ターゲット型に基づく型推論

● JavaSE5(5.0)から存在– メソッドジェネリクスの実型引数

– ダイアモンド演算子(JavaSE7)

Page 84: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

84

ターゲット型

● ある式の型として予期される型のこと

● List<Integer> l = new ArrayList<>();– “new ArrayList<>()”のターゲット型はList<Integer>

Page 85: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

85

ターゲット型が存在する文脈

● 変数宣言・・・ int n = …● 割り当て・・・ n = …● return文・・・ return …● 配列初期化子・・・new String[]{...}● 実引数・・・method(...)● 条件式 ?:・・・bool ? … : …● キャスト式 ・・・(Target)...● ラムダ式の本体・・・() -> …

例 exprのターゲット型

変数宣言 int n = expr 変数の型(int)

割り当て n = expr 変数の型(nの型)

return文 return expr 戻り値の型

配列初期化子 new String[]{expr, ...} 配列の型(String)

実引数 m(expr, ...) 仮引数の型

条件式 cond ? expr : expr 透過された型

キャスト式 (String)expr String

ラムダ式の本体 () -> expr 戻り値の型

Page 86: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

86

JavaSE7における適用可能箇所

メソッドジェネリクスの実型引数 ダイアモンド演算子

変数宣言 ○ ○

割り当て ○ ○

return文 ○ ○

配列初期化子 ○ -

実引数 × ×

条件式 × ×

キャスト式 ○ ×

ラムダ式の本体

Page 87: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

87

適用可能箇所の例(JavaSE7)

List<Integer> l = new ArrayList<>();new ArrayList<T>()

new ArrayList<Integer>()

● ArrayList<T> <: List<Integer>

– T =:= Integer

Page 88: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

88

適用不可能箇所の例(JavaSE7)

● 実引数におけるターゲット型推論

printStrings(new ArrayList<>());– void printStrings(List<String> l)

Page 89: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

89

適用不可能箇所の例(JavaSE7)

● 実引数におけるターゲット型推論

printStrings(new ArrayList<Object>());– void printStrings(List<String> l)

● コンパイルエラー

– Objectと推論される

Page 90: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

90

適用不可能箇所の例(JavaSE7)

● 条件式におけるターゲット型推論

List<Integer> list = bool ?

Collections.emptyList() :

new ArrayList<>();

Page 91: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

91

適用不可能箇所の例(JavaSE7)

● 条件式におけるターゲット型推論

List<Integer> list = bool ?

Collections.<Object>emptyList() :

new ArrayList<Object>();

● コンパイルエラー

– Objectと推論される

Page 92: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

92

JavaSE8における適用可能箇所

メソッドジェネリクスの実型引数 ダイアモンド演算子

変数宣言 ○ ○

割り当て ○ ○

return文 ○ ○

配列初期化子 ○ -

実引数 ○ ○

条件式 ○ ○

キャスト式 ○ ×?bug?(3/19現在)

ラムダ式の本体 ○ ○

Page 93: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

93

適用可能になった例(JavaSE8)

● 実引数におけるターゲット型推論

printStrings(new ArrayList<>());– void printStrings(List<String> l)

Page 94: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

94

適用可能になった例(JavaSE8)

● 実引数におけるターゲット型推論

printStrings(new ArrayList<String>());– void printStrings(List<String> l)

● 推論器が正しく働く

– ターゲット型よりStringと推論される

Page 95: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

95

適用可能になった例(JavaSE8)

● 条件式におけるターゲット型推論

List<Integer> list = bool ?

Collections.emptyList() :

new ArrayList<>();

Page 96: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

96

適用可能になった例(JavaSE8)

● 条件式におけるターゲット型推論

List<Integer> list = bool ?

Collections.<Integer>emptyList() :

new ArrayList<Integer>();

● 推論器が正しく働く

– ターゲット型よりIntegerと推論される

Page 97: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

97

JavaSE8における適用可能箇所

ラムダ式・メソッド参照

変数宣言 ○

割り当て ○

return文 ○

配列初期化子 ○

実引数 ○

条件式 ○

キャスト式 ○

ラムダ式の本体 ○

Page 98: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

98

2.より正確な推論

● 今までは簡易的な推論

● しばしば不正確な推論によりコンパイルエラー– 複雑な場合

Page 99: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

99

JavaSE7以前の推論

1.実引数の式の型を優先

2.実引数がない場合はターゲット型

Page 100: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

100

ターゲット型推論が働く例

List<Number> list =

Arrays.asList();

java.util.Arrays#<T> List<T> asList(T...)

● List<Number> =:= List<T>– T =:= Number

Page 101: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

101

不正確な推論の例(JavaSE7)

List<Number> list =

Arrays.asList(2, 5.5);

java.util.Arrays#<T> List<T> asList(T...)

Page 102: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

102

不正確な推論の例(JavaSE7)

List<Number> list =

Arrays.<T>asList(2, 5.5);

● T<:Object, T :>Integer,T:>Double(実引数より)

– T=:=Number & Comparable<...>

Page 103: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

103

不正確な推論の例(JavaSE7)

List<Number> list =

Arrays.<Number & Comparable<...>>asList(2, 5.5);

● コンパイルエラー

– Number & Comparable<? extends Number & Comparable<?>>と推論される

– List<Number & Comparable<...>>を

List<Number>として代入

Page 104: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

104

JavaSE8以降の推論

● 実引数の型とターゲット型を加味– グラフ推論

– より正確な型推論へ

Page 105: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

105

先の例(JavaSE8の場合)

List<Number> list =

Arrays.asList(2, 5.5);

Page 106: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

106

先の例(JavaSE8の場合)

List<Number> list =

Arrays.<T>asList(2, 5.5);

● T<:Object, T :>Integer,T:>Double(実引数より)

● T=Number(ターゲット型より)

– T=Number

Page 107: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

107

先の例(JavaSE8の場合)

List<Number> list =

Arrays.<Number>asList(2, 5.5);

● 正しく推論器が働く

– Numberと推論される

Page 108: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

108

マルチコアCPUコアライブラリ

ラムダ式・メソッド参照

実質的にfinal

型推論の強化

交差型キャスト

defaultメソッド

stat. intf. メソッド

Page 109: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

109

型キャスト

キャスト式に交差型を

Page 110: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

110

交差型?

● Intersection Type● JavaSE5(5.0)から存在

– ジェネリクスの型境界(@型仮引数)

– <T extends Runnable & Cloneable>● RunnableとCloneableを継承する任意の型T

● 型 & 型 & … & 型– 一つ目は参照型

– 二つ目以降はインターフェース

Page 111: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

111

交差型キャスト

● (型 & 型 & … & 型)式

● 主にラムダ式・メソッド参照と使用する

Page 112: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

112

もしも交差型キャストがなかったら

● SerializableでRunnableなインターフェース– 関数型インターフェース

– ラムダ式でインスタンス化したい

– インターフェースを定義する必要がある

Page 113: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

113

もしも交差型キャストがなかったら

interface SRunnable implements

Runnable, Serializeable {}

sendRunnable((SRunnable) () -> {/* */});

Page 114: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

114

もしも交差型キャストがなかったら

interface SRunnable implements

Runnable, Serializeable {}

sendRunnable((SRunnable) () -> {/* */});

Page 115: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

115

交差型キャスト+ラムダ式

sendRunnable((Runnable & Serializable)

() -> {/* */});

● 型合成される

Page 116: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

116

マルチコアCPUコアライブラリ

ラムダ式・メソッド参照

実質的にfinal

型推論の強化

交差型キャスト

defaultメソッド

stat. intf. メソッド

Page 117: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

117

<interface>PublishedInterface

+already()+exist()+methods()

Page 118: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

118

<interface>PublishedInterface

+already()+exist()+methods()

ReferenceImpl

+already()+exist()+methods()

AnotherImpl

+already()+exist()+methods()

UserImpl

+already()+exist()+methods()

Page 119: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

119

<interface>PublishedInterface+already()+exist()+methods()

+newMethod()

ReferenceImpl

+already()+exist()+methods()

AnotherImpl

+already()+exist()+methods()

UserImpl

+already()+exist()+methods()

Page 120: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

120

<interface>PublishedInterface+already()+exist()+methods()

+newMethod()

ReferenceImpl

+already()+exist()+methods()

AnotherImpl

+already()+exist()+methods()

UserImpl

+already()+exist()+methods()

Page 121: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

121

インターフェースに拡張性を

● 新しいメソッドを加えても互換性を保つ

● デフォルトメソッド– デフォルトの実装を提供する

– インターフェースに実装

– 実装が提供されない場合に使用される

Page 122: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

122

デフォルトメソッド

interface Person {

Sex getSex();

default boolean isMan() {

return getSex() == Sex.MAN;

}

}

Page 123: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

123

デフォルトメソッド

class PersonImpl implements Person {

public Sex getSex() {/*...*/}

// isManへの実装はなくてもOK

// Person#isManが使われる

}

Page 124: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

124

デフォルトメソッド

class PersonImpl implements Person {

public Sex getSex() {/*...*/}

public boolean isMan() {/*...*/}

}

● オーバーライド可

Page 125: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

125

デフォルトメソッド

● default修飾子

● publicメソッドとなる– 既存のインターフェースメソッドと同様

● strictfp修飾のみ可● 具象クラスで実装が提供されなくても無問題

● 拡張性を実現できた– 新たな問題が・・・

Page 126: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

126

実装の多重継承問題

Page 127: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

127

多重継承

class BasicPerson {

public boolean isMan() {/*...*/}

}

class ComplexPerson extends BasicPerson

implements Person {

public Sex getSex() {/*...*/}

}

Page 128: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

128

多重継承

BasicPerson#isMan

Person#isMan

ComplexPerson#isMan

Page 129: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

129

“Class always win”

Page 130: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

130

クラスで定義された実装が常に勝つ

Page 131: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

131

Class always win

class BasicPerson {

public boolean isMan() {/*...*/}

}

class ComplexPerson extends BasicPerson implements Person {

public Sex getSex() {/*...*/}

}

● BasicPerson#isManが使われる– “Class always win”

Page 132: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

132

親インターフェースの呼び出し

class ComplexPerson extends BasicPerson implements Person {

public Sex getSex() {/*...*/}

public boolean isMan() {

return Person.super.isMan();

}

}● インターフェース名.super.メソッド名(...)

Page 133: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

133

クラスを介さない多重継承

interface Base1 {default void m() {}}

Page 134: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

134

クラスを介さない多重継承

interface Base1 {default void m() {}}

interface Base2 {default void m() {}}

Page 135: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

135

クラスを介さない多重継承

interface Base1 {default void m() {}}

interface Base2 {default void m() {}}

interface ExBase extends Base1, Base2 {}

Page 136: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

136

多重継承

Base1#m Base2#m

ExBase#m

Page 137: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

137

クラスを介さない多重継承

interface ExBase extends

Base1, Base2 {}

● コンパイルエラー– オーバーライドして選択

Page 138: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

138

クラスを介さない多重継承

interface ExBase extends

Base1, Base2 {

default void m() {

Base1.super.m();

}

}

Page 139: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

139

多重継承は怖くない!!

● 大原則1:Class always win– クラスで定義された実装が常に勝つ

● 大原則2:いつでもオーバーライドできる– 親クラスでfinal修飾されてたら別

– インターフェースの実装を呼べる

Page 140: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

140

Objectメソッドのデフォルトメソッド

● Objectで定義されたpublicメソッド– そもそもデフォルトの実装

● Objectのpublicメソッドのデフォルトメソッドは不可– interface I {default String toString() {/* */}}– コンパイルエラー

Page 141: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

141

マルチコアCPUコアライブラリ

ラムダ式・メソッド参照

実質的にfinal

型推論の強化

交差型キャスト

defaultメソッド

stat. intf. メソッド

Page 142: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

142

staticインターフェースメソッド

● staticなインターフェースメソッド

● 常にpublic修飾– 他のインターフェースのメソッドと同様

● strictfp修飾可– デフォルト実装と同様

Page 143: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

143

staticインターフェースメソッドの例

interface Example {

static void method() {/* */}

}

Page 144: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

144

staticインターフェースメソッドの例

interface Example {

static strictfp void method() {/* */}

}

● strictfp修飾可

Page 145: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

145

staticインターフェースメソッドの継承

● 継承されない

– クラスメソッドと大きく違う

interface Example2 extends Example {}

Example2.method()はコンパイルエラー

Page 146: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

146

Interesting Example

● publicでstaticなメソッド– 人生で最初に書いたメソッド

Page 147: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

147

Interesting Example

● publicでstaticなメソッド– 人生で最初に書いたメソッド

public static void main( String[] args)

Page 148: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

148

main in Interface

interface EntryPoint {

public static void main(String[] args) {

/* ... */

}

}● 正しく動く

Page 149: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

149

マルチコアCPUコアライブラリ

ラムダ式・メソッド参照

実質的にfinal

型推論の強化

交差型キャスト

defaultメソッド

stat. intf. メソッド

Page 150: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

150

Library Enhancements

StreamAPI

IO/NIOJCF

Optional

AndMore...

Page 151: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

151

Library Enhancements

StreamAPI

IO/NIOJCF

Optional

AndMore...

Page 152: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

152

No more 外部イテレーション

● 外部イテレーションは並列化困難

● 内部イテレーションベースのライブラリへ– 並列化が容易に

Page 153: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

153

外部イテレーション

● イテレーションが外にさらされている– for,while文

for (Student s : students) {

}

Page 154: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

154

内部イテレーションライブラリ

StreamAPI

Page 155: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

155

StreamAPI

java.util.stream.

● Stream● IntStream● LongStream● DoubleStream

– ソースから生成される

– 中間操作と終端操作でデータを弄る

– 並列化が容易

Page 156: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

156

Collection

配列

BufferReader

etc...

Stream

IntStream

LongStream

DoubleStream

中間操作

終端操作

j.u.stream.*Source

Page 157: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

157

Collection

配列

BufferReader

etc...

Stream

IntStream

LongStream

DoubleStream

中間操作

終端操作

j.u.stream.*Source

Page 158: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

158

Make Streamsソース メソッド 使用例

Collection Collection#stream list.stream()

配列 Arrays#stream Arrays.stream(args)

BufferedReader BufferedReader#lines br.lines()

n〜m-1までの数値 IntStream#range IntStream.range(n, m)

n〜mまでの数値 IntStream#rangeClosed IntStream.rangeClosed(n, m)

任意の要素 Stream#of Stream.of(“J”, “a”, “v”, “a”)

Page 159: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

159

Collection

配列

BufferReader

etc...

Stream

IntStream

LongStream

DoubleStream

中間操作

終端操作

j.u.stream.*Source

Page 160: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

160

java.util.stream.

StreamAPI 要素の型

Stream<T> T(参照型)

IntStream int(プリミティブ型)

LongStream long(プリミティブ型)

DoubleStream double(プリミティブ型)

Page 161: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

161

2 types of Stream

Sequential Stream

Parallel Stream

Page 162: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

162

Change the type of Stream

Sequential Stream

Parallel Stream

parallel() sequential()

Page 163: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

163

Collection

配列

BufferReader

etc...

Stream

IntStream

LongStream

DoubleStream

中間操作

終端操作

j.u.stream.*Source

Page 164: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

164

中間操作?

● filterやmapなど– Streamを返すメソッド

● 終端操作が行われるまで処理されない– 遅延される

Page 165: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

165

主要な中間操作

メソッド名 概要 使用例

filter フィルタリング s.filter(n -> n % 2 == 0)

map 写像・変換 s.map(p -> p.getName())

flatMap 写像・変換&平坦化 s.flatMap(room -> room.getPersons().stream())

distinct 同一の要素を除外 s.distinct()

sorted 並び替え s.sorted((p1, p2) -> compare(p1.age, p2.age))

peekデバッグ向け

forEachs.peek(e -> System.out.println(e))

limit 要素数制限 s.limit(5)

skip 読み飛ばす s.skip(5)

Page 166: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

166

Collection

配列

BufferReader

etc...

Stream

IntStream

LongStream

DoubleStream

非終端操作

終端操作

j.u.stream.*Source

Page 167: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

167

終端操作?

● forEachやreduceやcollectなど– Streamを返さないメソッド

● 遅延されていた中間操作を確定

Page 168: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

168

主要な終端操作

メソッド名 概要 使用例

forEach 反復処理 s.forEach(e -> System.out.println(e))

reduce 畳み込み演算 s.reduce(1, (n1, n2) -> n1 * n2)

collect 集約化 s.collect(Collectors.toList())

toArray 配列化 s.toArray(String[]::new)

min/max 最小値/最大値 s.min(String::compareToIgnoreCase)

count 要素数 s.count()

Page 169: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

169

0から10まで出力したい

for (int i = 0; i <= 10; i++) {

System.out.println(i);

}

Page 170: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

170

forEach[終端操作]

T->void[j.u.function.Consumer<T>#void accept(T)]

● forEach(T -> void)– 各要素に引数で渡した処理を行なう

– s.forEach(t -> {/**/});

Page 171: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

171

0から10まで出力したい

for (int i = 0; i <= 10; i++) {

System.out.println(i);

}

IntStream.rangeClose(0, 10)

.forEach(i -> System.out.println(i));

Page 172: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

172

0から10まで出力したい

for (int i = 0; i <= 10; i++) {

System.out.println(i);

}

IntStream.rangeClose(0, 10)

.forEach(System.out::println);

Page 173: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

173

0から10までの偶数を出力したい

for (int i = 0; i <= 10; i++) {

if (i % 2 == 0) {

System.out.println(i);

}

}

Page 174: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

174

filter[中間操作]

● filter(T -> boolean)– フィルタリング

– 各要素を引数に適用しtrueを返したもののみ残す

– s.filter(Objects::nonNull) // nullを除外

Page 175: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

175

filter[中間操作]

T->boolean[j.u.function.Predicate<T>#boolean test(T)]

Page 176: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

176

0から10までの偶数を出力したい

IntStream.rangeClose(0, 10)

.filter(i -> i % 2 == 0)

.forEach(System.out::println);

Page 177: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

177

Personのリストから名前を出力

for (Person p : persons) {

System.out.println(p.getName());

}

Page 178: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

178

map[中間操作]

● map(T -> R)– 写像・変換

– 各要素を引数に適用した結果のStreamを作る

– personStream.map(p -> p.getName())

Page 179: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

179

map[中間操作]

T -> R[java.util.function.Function<T, R>#R map(T)]

R

Page 180: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

180

Personのリストから名前を出力

persons.stream()

.map(p -> p.getName())

.forEach(n -> System.out.println(n));

Page 181: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

181

Personのリストから名前を出力

persons.stream()

.map(Person::getName)

.forEach(System.out::println);

Page 182: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

182

Streamを横断するmap

Stream<T> IntStream

LongStream DoubleStream

#mapToObj

#mapToInt

#mapToLong

#mapToDouble

#mapTo D

o uble

#ma pTo Lon g

#mapToInt

Page 183: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

183

Personのリストから名前のリスト

List<String> names = new ArrayList<>();

for (Person p : persons) {

names.add(p.getName());

}

Page 184: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

184

collect[終端処理]

● collect(Collector<T, R>)● collect(() -> R, (R, T) -> void, (R, R) -> void)

– 集約処理を行なう

– stream.collect(Collectors.toList())

– strings.collect(StringBuilder::new,

StringBuilder::apped, StringBuilder::apped)

Page 185: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

185

Personのリストから名前のリスト

persons.stream()

.map(Person::getName)

.collect(Collectors.toList())

Page 186: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

186

Sequentialcollect(SB::new, SB::append, SB::append)

H e l l o , W o r l d !

Page 187: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

187

H e l l o , W o r l d !

SB

Sequentialcollect(SB::new, SB::append, SB::append)

Page 188: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

188

H e l l o , W o r l d !

SB

Sequentialcollect(SB::new, SB::append, SB::append)

Page 189: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

189

H e l l o , W o r l d !

SB

Sequentialcollect(SB::new, SB::append, SB::append)

Page 190: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

190

Parallelcollect(SB::new, SB::append, SB::append)

H e l l o , W o r l d !

Page 191: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

191

Parallelcollect(SB::new, SB::append, SB::append)

H e l l o , W o r l d !

Split!!

Page 192: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

192

Parallelcollect(SB::new, SB::append, SB::append)

H e l l o , W o r l d !

Page 193: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

193

Parallelcollect(SB::new, SB::append, SB::append)

H e l l o , W o r l d !

He Wo

Page 194: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

194

Parallelcollect(SB::new, SB::append, SB::append)

H e l l o , W o r l d !

He Wo

Page 195: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

195

Parallelcollect(SB::new, SB::append, SB::append)

H e l l o , W o r l d !

He Wo

Page 196: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

196

Parallelcollect(SB::new, SB::append, SB::append)

H e l l o , W o r l d !

He WoSBll SBd!

Page 197: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

197

Parallelcollect(SB::new, SB::append, SB::append)

H e l l o , W o r l d !

He WoSBll SBd!

Page 198: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

198

Parallelcollect(SB::new, SB::append, SB::append)

H e l l o , W o r l d !

Hell Wo SBd!

Page 199: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

199

Parallelcollect(SB::new, SB::append, SB::append)

H e l l o , W o r l d !

Hell Wo SBd!

Page 200: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

200

Parallelcollect(SB::new, SB::append, SB::append)

H e l l o , W o r l d !

Hell Wo SBd!SBo, SBrl

Page 201: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

201

Parallelcollect(SB::new, SB::append, SB::append)

H e l l o , W o r l d !

Hell Wo SBd!SBo, SBrl

Page 202: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

202

Parallelcollect(SB::new, SB::append, SB::append)

H e l l o , W o r l d !

Hello, Worl SBd!

Page 203: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

203

Parallelcollect(SB::new, SB::append, SB::append)

H e l l o , W o r l d !

Hello, Worl SBd!

Page 204: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

204

Parallelcollect(SB::new, SB::append, SB::append)

H e l l o , W o r l d !

Hello,Worl SBd!

Page 205: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

205

Parallelcollect(SB::new, SB::append, SB::append)

H e l l o , W o r l d !

Hello,Worl SBd!

Page 206: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

206

Parallelcollect(SB::new, SB::append, SB::append)

H e l l o , W o r l d !

Hello,World!

Page 207: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

207

Putting it together

学生のリスト(students)の内

2年生で

GPAが3.5以上ある学生の

学籍番号の

リストを生成する

Page 208: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

208

Putting it together

List<StudentID> list = new ArrayList<>();

for (Student s : students) {

if (s.getGrade() == 2 &&

s.getGPA() >= 3.5) {

list.add(s.getID());

}

}

Page 209: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

209

Putting it together

学生のリスト(students)の内

2年生で

GPAが3.5以上ある学生の

学籍番号の

リストを生成する

Page 210: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

210

Putting it together

students.stream()

2年生で

GPAが3.5以上ある学生の

学籍番号の

リストを生成する

Page 211: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

211

Putting it together

students.stream()

.filter(s -> s.getGrade() == 2)

GPAが3.5以上ある学生の

学籍番号の

リストを生成する

Page 212: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

212

Putting it together

students.stream()

.filter(s -> s.getGrade() == 2)

.filter(s -> s.getGPA() >= 3.5)学籍番号の

リストを生成する

Page 213: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

213

Putting it together

students.stream()

.filter(s -> s.getGrade() == 2)

.filter(s -> s.getGPA() >= 3.5)

.map(Student::getID)リストを生成する

Page 214: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

214

Putting it together

students.stream()

.filter(s -> s.getGrade() == 2)

.filter(s -> s.getGPA() >= 3.5)

.map(Student::getID)

.collect(Collectors.toList())

Page 215: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

215

Putting it together

students.stream().parallel()

.filter(s -> s.getGrade() == 2)

.filter(s -> s.getGPA() >= 3.5)

.map(Student::getID)

.collect(Collectors.toList())

Page 216: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

216

Project Lambdaまとめ

● もともとはマルチコア対応

● 結果としては汎用的な仕様に– ラムダ式等

– コアライブラリ

● よりスマートなコードへ

Page 217: 徹底解説!Project Lambdaのすべて in Fukuoka #j8fk

217

Thank you for your listeningEnjoy JavaSE8