Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
きつねさんと学ぶ
Lambda式&StreamAPIハンズオン
2015/7/11 @ 関ジャバ
2
Who are you?
吉田真也(@bitter_fox, @shinyafox)
●
立命館大学 情報理工学部 情報システム学科
– 高性能計算機ソフトウェアシステム研究室
● 立命館コンピュータクラブ(RCC)
● http://ww...
3
Project Kulla
ハンズオンの諸注意
1.わからないことがあったら
TAさんを呼んでください
2.IDEの自動変換機能禁止
3.本ハンズオンでは
メソッド参照は使用しません
Main1
ラムダ式導入
匿名クラスで書かれたコードを
ラムダ式で置き換えてみましょう
ラムダ式
● 関数型インターフェースを実装&インスタンス化
する
– メソッドが一つのインターフェース
– Runnable, Function<T>, etc...
● (引数) -> {文}
● (引数) -> 式
Main2
関数型インターフェース
自分で関数型インターフェースを定義してみよう
関数型インターフェース
●
メソッドが一つのインターフェース
interface F {
void exec0();
}
●
@FunctionalInterfaceアノテーション
– コンパイル時に関数型インターフェースかを検査
Any question?
Main3
内部イテレーションへ
(拡張)for文をIterable#forEachで書き換えよう
Main3
List<Integer>の要素を
一行ずつ出力
for (Integer n : list) {
System.out.println(n);
}
外部イテレーション?
内部イテレーション?
●
外部イテレーション
– イテレーションをユーザコードが行う
– for文,while文
– 並列化が困難
●
ユーザコードの大幅な変更が必要
●
内部イテレーション
– イテレーションをライブラリ...
Iterable#forEach
list.forEach(n ->
System.out.println(n));
Main4
StreamAPI導入
複雑なイテレーションをStreamAPIで書いてみよう
Main4
List<Integer>の
2で割り切れる
要素だけを一行ずつ出力
StreamAPI
● 内部イテレーション&パイプライン化
●
汎用性高い
– あらゆる形式のデータ列に対応可
● Collection
●
値の範囲
●
任意の値
– データ列自体は保持していない
●
データへのアクセス手段を保持
21
StreamAPI
java.util.stream.
Stream<T>
IntStream
LongStream
DoubleStream
– ソースから生成される
– 中間操作と終端操作でデータを弄る
– 並列化が容易
22
Collection
配列
BufferReader
etc...
Stream
IntStream
LongStream
DoubleStream
中間操作
終端操作
j.u.stream.*Source
23
中間操作?
● Stream#filterやmapなど
– Streamを返すメソッド
●
終端操作が行われるまで処理されない
– 遅延される
24
終端操作?
● Stream#forEachやreduceやcollectなど
– Streamを返さないメソッド
●
遅延されていた中間操作を確定
– 1回のループで済む
25
StreamAPIで書くポイント
●
ソース,中間操作,終端操作を意識する
● forEachで副作用を与えて何でも書こうとしない
– forEachを使わずに実現する方法が存在する(はず)
– 出力などの副作用はOK
Main4(再掲)
List<Integer>の
2で割り切れる
要素だけを一行ずつ出力
Main4
List<Integer>の ソース
2で割り切れる filter[中間操作]
要素だけを一行ずつ出力 forEach[終端操作]
Collection<T>からStream<T>
● Collection<T>#stream()
– parallelStream()で並列Streamも取得可
29
filter[中間]
● filter(T -> boolean)
– フィルタリング
– 各要素を引数に適用しtrueを返したもののみ残す
– filterの引数には欲しい値の条件を書く
– s.filter(Objects::nonN...
Main5
値の変換を行う中間操作をしてみよう
Main5
List<Person>から
Personの名前を
一行ずつ出力
Main5
List<Person>から ソース
Personの名前を map[中間操作]
一行ずつ出力 forEach[終端操作]
33
map[中間操作]
● map(T -> R)
– 写像・変換
– 各要素を引数に適用した結果のStreamを作る
– personStream.map(p -> p.getName())
– seq.map(n -> n * 2)
St...
34
Streamを横断するmap
Stream<T> IntStream
LongStream DoubleStream
#mapToObj
#mapToInt
#mapToLong
#mapToDouble
#mapToDouble
#ma...
Main6
複数の要素から一つの値へ
Main6
ある数値の範囲の
総和を求める
乱数生成器Randomから
指定された個数の数値の
平均を求める
Main6
ある数値の範囲の ソース
総和を求める 終端操作
乱数生成器Randomから ソース
指定された個数の数値の 中間操作
平均を求める 終端操作
値の範囲からStream
● IntStream.range(start, end)
– start〜end(end含まない)のIntStream
– end含める場合はrangeClosed
39
reduce[終端]
● Optional<T> reduce((T, T) -> T)
● T reduce(T, (T, T) -> T)
● U reduce(U, (U, T) -> U, (U, U) -> U)
– 集約
– ...
40
reduce[終端]
41
reduce[終端]
42
reduce[終端]
43
reduce[終端]
44
reduce[終端]
45
reduce[終端]
46
並列reduce
47
並列reduce
48
並列reduce
49
並列reduce
50
並列reduce
51
並列reduce
6
52
並列reduce
6
53
sum[終端]
● int sum()
● long sum()
● double sum()
– 総和を求める
●
そのものズバリ
– s.sum()
Stream<T>
IntStream
LongStream
DoubleStream
54
summaryStatistics[終端]
● XxxSummaryStatistics
summaryStatistics()
– 統計処理
●
合計,平均,最大,最小,個数
– stream.summaryStatistics().g...
Main6
ある数値の範囲の ソース
総和を求める 終端操作
乱数生成器Randomから ソース
指定された個数の数値の 中間操作
平均を求める 終端操作
56
RandomからStream
● Random#doubles()
– DoubleStream
– 無限のStream
– limitと併用
● Random#doubles(n)
– n個の要素のDoubleStream
57
Ave, max, min[終端]
● average(), max(), min()
– Optional系を返す
– 平均,最大,最小値を求める
Stream<T>
IntStream
LongStream
DoubleStream
Main6_1
Streamと並列処理
59
Change the type of Stream
Sequential Stream
Parallel Stream
parallel() sequential()
60
Streamと並列処理
●
並列化したら早くなるのか
– 一概には言えない・・・
●
データ数依存
● CPU依存
●
操作依存
– 早くなるものもある
– 並列化に際してはベンチマーク必須
Any question?
Main7
ファイルからの読み出しと
リストへの集約
Main7
ファイルから
“{“か”}”で終わる行を
出力する
ファイルから
“{“か”}”で終わる行を
リストに入れる
Main7
ファイルから
“{“か”}”で終わる行を
出力する
ファイルから
“{“か”}”で終わる行を
リストに入れる
Main7
ファイルから ソース
“{“か”}”で終わる行を 中間操作
出力する 終端操作
ファイルから ソース
“{“か”}”で終わる行を 中間操作
リストに入れる 終端操作
ファイルからStream<String>
● BufferedReader#lines()
● j.nio.file.Files#lines(Path)
– 一行ずつのStream
– Closeしなければいけない
●
twr利用可
try (...
Main7
ファイルから ソース
“{“か”}”で終わる行を 中間操作
出力する 終端操作
ファイルから ソース
“{“か”}”で終わる行を 中間操作
リストに入れる 終端操作
68
collect
● R collect(() -> R, (R, T) -> R, (R, R) -> void)
● R collect(Collector<T, ?, R>)
– 集約処理
– R:集約先のオブジェクト
– () ->...
69
Collectors#toXxx
● toCollection()
● toList()
● toSet()
– リストなどへの集約をするCollectorの生成
Main8
Streamを返す変換を平坦化する
Main8
List<Campany>から
List<Car>を取得し
すべての車のうちの
軽自動車のみの
車名の
リストを作る
Main8
List<Campany>から ソース
List<Car>を取得し 中間操作
すべての車のうちの
軽自動車のみの filter
車名の map
リストを作る collect(toList())
Streamを返すmap
H e l l
H e l l o
H e l l o , W
H e l
Stream<Stream<R>>Stream<T>
flatMap
H e l l
H e l l o
H e l l o , W
H e l
Stream<R>Stream<T>
flatMap
● flatMap(T -> Stream<R>)
– 写像・変換 + 平坦化
– 平坦化されたStream<R>
– companieStream.flatMap(c → c.getList().stream())
Main9
文字列の連結
Main9
List<Person>から
Personの名前を
,区切りで連結する
Main9
List<Person>から ソース
Personの名前を 中間操作
,区切りで連結する 終端操作
79
Collectors#joining
● joining()
● joining(delimiter)
● joining(delimiter, prefix, suffix)
– 文字列の連結をするCollectorを返す
– 単なる連...
Main10
同じ値でグループ化
Main10
List<People>から
同じ性別でPeopleをグループ化
List<People>から
同じ名字でPeopleの名前をグループ化
82
Collectors#groupingBy
● groupingBy(T -> K)
– Kの同じ値でグループ化
– Map<K, List<T>>にする
83
Collectors#groupingBy
● groupingBy(T -> K, Collector)
– 第二引数はMapの値へのCollector
– groupingBy(..., toSet()) : Map<K, Set<T...
84
Collectors#mapping
● mapping(T -> U, Collector)
– 値の変換を行って集約するCollector
Main10_1
並列グループ化
groupingBy vs.
groupingByConcurrent
● groupingByでも並列化できる
– 分割統治法
– Map<K, List<V>>同士の連結が起きる
●
逐次よりも遅くなる可能性
● groupingByCon...
87
Parallel
groupingBy
H e l l o , W o r l d !
88
Parallel
groupingBy
Split!!
89
Parallel
groupingBy
Map Map Map Map
90
Parallel
groupingBy
Map Map Map MapMap Map
91
Parallel
groupingBy
Map MapMap Map
92
Parallel
groupingBy
Map Map
93
H e l o , W o r l d !
Map
parallel
groupingByConcurrent
Any question?
きつねさんと学ぶ Lambda式&StreamAPIハンズオン[関ジャバ2015/7/11] #kanjava
Upcoming SlideShare
Loading in …5
×
Upcoming SlideShare
Lt (コピー)
Next
Download to read offline and view in fullscreen.

5

Share

Download to read offline

きつねさんと学ぶ Lambda式&StreamAPIハンズオン[関ジャバ2015/7/11] #kanjava

Download to read offline

きつねさんと学ぶ Lambda式&StreamAPIハンズオン

Related Books

Free with a 30 day trial from Scribd

See all

きつねさんと学ぶ Lambda式&StreamAPIハンズオン[関ジャバ2015/7/11] #kanjava

  1. 1. きつねさんと学ぶ Lambda式&StreamAPIハンズオン 2015/7/11 @ 関ジャバ
  2. 2. 2 Who are you? 吉田真也(@bitter_fox, @shinyafox) ● 立命館大学 情報理工学部 情報システム学科 – 高性能計算機ソフトウェアシステム研究室 ● 立命館コンピュータクラブ(RCC) ● http://www.rcc.ritsumei.ac.jp/ ● OpenJDKコミッタ – Project Kulla
  3. 3. 3 Project Kulla
  4. 4. ハンズオンの諸注意
  5. 5. 1.わからないことがあったら TAさんを呼んでください
  6. 6. 2.IDEの自動変換機能禁止
  7. 7. 3.本ハンズオンでは メソッド参照は使用しません
  8. 8. Main1 ラムダ式導入 匿名クラスで書かれたコードを ラムダ式で置き換えてみましょう
  9. 9. ラムダ式 ● 関数型インターフェースを実装&インスタンス化 する – メソッドが一つのインターフェース – Runnable, Function<T>, etc... ● (引数) -> {文} ● (引数) -> 式
  10. 10. Main2 関数型インターフェース 自分で関数型インターフェースを定義してみよう
  11. 11. 関数型インターフェース ● メソッドが一つのインターフェース interface F { void exec0(); } ● @FunctionalInterfaceアノテーション – コンパイル時に関数型インターフェースかを検査
  12. 12. Any question?
  13. 13. Main3 内部イテレーションへ (拡張)for文をIterable#forEachで書き換えよう
  14. 14. Main3 List<Integer>の要素を 一行ずつ出力 for (Integer n : list) { System.out.println(n); }
  15. 15. 外部イテレーション? 内部イテレーション? ● 外部イテレーション – イテレーションをユーザコードが行う – for文,while文 – 並列化が困難 ● ユーザコードの大幅な変更が必要 ● 内部イテレーション – イテレーションをライブラリが行う – イテレーション以外の処理を受け取る – 並列化が容易 ● イテレーションの方法を簡単に切り替えられる ● ユーザコードの変更は最小限
  16. 16. Iterable#forEach list.forEach(n -> System.out.println(n));
  17. 17. Main4 StreamAPI導入 複雑なイテレーションをStreamAPIで書いてみよう
  18. 18. Main4 List<Integer>の 2で割り切れる 要素だけを一行ずつ出力
  19. 19. StreamAPI ● 内部イテレーション&パイプライン化 ● 汎用性高い – あらゆる形式のデータ列に対応可 ● Collection ● 値の範囲 ● 任意の値 – データ列自体は保持していない ● データへのアクセス手段を保持
  20. 20. 21 StreamAPI java.util.stream. Stream<T> IntStream LongStream DoubleStream – ソースから生成される – 中間操作と終端操作でデータを弄る – 並列化が容易
  21. 21. 22 Collection 配列 BufferReader etc... Stream IntStream LongStream DoubleStream 中間操作 終端操作 j.u.stream.*Source
  22. 22. 23 中間操作? ● Stream#filterやmapなど – Streamを返すメソッド ● 終端操作が行われるまで処理されない – 遅延される
  23. 23. 24 終端操作? ● Stream#forEachやreduceやcollectなど – Streamを返さないメソッド ● 遅延されていた中間操作を確定 – 1回のループで済む
  24. 24. 25 StreamAPIで書くポイント ● ソース,中間操作,終端操作を意識する ● forEachで副作用を与えて何でも書こうとしない – forEachを使わずに実現する方法が存在する(はず) – 出力などの副作用はOK
  25. 25. Main4(再掲) List<Integer>の 2で割り切れる 要素だけを一行ずつ出力
  26. 26. Main4 List<Integer>の ソース 2で割り切れる filter[中間操作] 要素だけを一行ずつ出力 forEach[終端操作]
  27. 27. Collection<T>からStream<T> ● Collection<T>#stream() – parallelStream()で並列Streamも取得可
  28. 28. 29 filter[中間] ● filter(T -> boolean) – フィルタリング – 各要素を引数に適用しtrueを返したもののみ残す – filterの引数には欲しい値の条件を書く – s.filter(Objects::nonNull) // nullを除外 Stream<T> IntStream LongStream DoubleStream
  29. 29. Main5 値の変換を行う中間操作をしてみよう
  30. 30. Main5 List<Person>から Personの名前を 一行ずつ出力
  31. 31. Main5 List<Person>から ソース Personの名前を map[中間操作] 一行ずつ出力 forEach[終端操作]
  32. 32. 33 map[中間操作] ● map(T -> R) – 写像・変換 – 各要素を引数に適用した結果のStreamを作る – personStream.map(p -> p.getName()) – seq.map(n -> n * 2) Stream<T> IntStream LongStream DoubleStream
  33. 33. 34 Streamを横断するmap Stream<T> IntStream LongStream DoubleStream #mapToObj #mapToInt #mapToLong #mapToDouble #mapToDouble #mapToLong #mapToInt
  34. 34. Main6 複数の要素から一つの値へ
  35. 35. Main6 ある数値の範囲の 総和を求める 乱数生成器Randomから 指定された個数の数値の 平均を求める
  36. 36. Main6 ある数値の範囲の ソース 総和を求める 終端操作 乱数生成器Randomから ソース 指定された個数の数値の 中間操作 平均を求める 終端操作
  37. 37. 値の範囲からStream ● IntStream.range(start, end) – start〜end(end含まない)のIntStream – end含める場合はrangeClosed
  38. 38. 39 reduce[終端] ● Optional<T> reduce((T, T) -> T) ● T reduce(T, (T, T) -> T) ● U reduce(U, (U, T) -> U, (U, U) -> U) – 集約 – s.reduce((n, m) -> n < m ? n : m) ● Optional – 値が無いという状態を表すことができる Stream<T> IntStream LongStream DoubleStream
  39. 39. 40 reduce[終端]
  40. 40. 41 reduce[終端]
  41. 41. 42 reduce[終端]
  42. 42. 43 reduce[終端]
  43. 43. 44 reduce[終端]
  44. 44. 45 reduce[終端]
  45. 45. 46 並列reduce
  46. 46. 47 並列reduce
  47. 47. 48 並列reduce
  48. 48. 49 並列reduce
  49. 49. 50 並列reduce
  50. 50. 51 並列reduce 6
  51. 51. 52 並列reduce 6
  52. 52. 53 sum[終端] ● int sum() ● long sum() ● double sum() – 総和を求める ● そのものズバリ – s.sum() Stream<T> IntStream LongStream DoubleStream
  53. 53. 54 summaryStatistics[終端] ● XxxSummaryStatistics summaryStatistics() – 統計処理 ● 合計,平均,最大,最小,個数 – stream.summaryStatistics().getSum() – 複数の統計的な値を求める場合 Stream<T> IntStream LongStream DoubleStream
  54. 54. Main6 ある数値の範囲の ソース 総和を求める 終端操作 乱数生成器Randomから ソース 指定された個数の数値の 中間操作 平均を求める 終端操作
  55. 55. 56 RandomからStream ● Random#doubles() – DoubleStream – 無限のStream – limitと併用 ● Random#doubles(n) – n個の要素のDoubleStream
  56. 56. 57 Ave, max, min[終端] ● average(), max(), min() – Optional系を返す – 平均,最大,最小値を求める Stream<T> IntStream LongStream DoubleStream
  57. 57. Main6_1 Streamと並列処理
  58. 58. 59 Change the type of Stream Sequential Stream Parallel Stream parallel() sequential()
  59. 59. 60 Streamと並列処理 ● 並列化したら早くなるのか – 一概には言えない・・・ ● データ数依存 ● CPU依存 ● 操作依存 – 早くなるものもある – 並列化に際してはベンチマーク必須
  60. 60. Any question?
  61. 61. Main7 ファイルからの読み出しと リストへの集約
  62. 62. Main7 ファイルから “{“か”}”で終わる行を 出力する ファイルから “{“か”}”で終わる行を リストに入れる
  63. 63. Main7 ファイルから “{“か”}”で終わる行を 出力する ファイルから “{“か”}”で終わる行を リストに入れる
  64. 64. Main7 ファイルから ソース “{“か”}”で終わる行を 中間操作 出力する 終端操作 ファイルから ソース “{“か”}”で終わる行を 中間操作 リストに入れる 終端操作
  65. 65. ファイルからStream<String> ● BufferedReader#lines() ● j.nio.file.Files#lines(Path) – 一行ずつのStream – Closeしなければいけない ● twr利用可 try (Stream<String> lines = Files.lines(path)) { }
  66. 66. Main7 ファイルから ソース “{“か”}”で終わる行を 中間操作 出力する 終端操作 ファイルから ソース “{“か”}”で終わる行を 中間操作 リストに入れる 終端操作
  67. 67. 68 collect ● R collect(() -> R, (R, T) -> R, (R, R) -> void) ● R collect(Collector<T, ?, R>) – 集約処理 – R:集約先のオブジェクト – () -> R:集約先のオブジェクトの生成 – (R, T) -> R:集約先のオブジェクトRに要素Tを集約 – (R, R) -> void:集約先のオブジェクトR同士のcombine ● 並列処理用
  68. 68. 69 Collectors#toXxx ● toCollection() ● toList() ● toSet() – リストなどへの集約をするCollectorの生成
  69. 69. Main8 Streamを返す変換を平坦化する
  70. 70. Main8 List<Campany>から List<Car>を取得し すべての車のうちの 軽自動車のみの 車名の リストを作る
  71. 71. Main8 List<Campany>から ソース List<Car>を取得し 中間操作 すべての車のうちの 軽自動車のみの filter 車名の map リストを作る collect(toList())
  72. 72. Streamを返すmap H e l l H e l l o H e l l o , W H e l Stream<Stream<R>>Stream<T>
  73. 73. flatMap H e l l H e l l o H e l l o , W H e l Stream<R>Stream<T>
  74. 74. flatMap ● flatMap(T -> Stream<R>) – 写像・変換 + 平坦化 – 平坦化されたStream<R> – companieStream.flatMap(c → c.getList().stream())
  75. 75. Main9 文字列の連結
  76. 76. Main9 List<Person>から Personの名前を ,区切りで連結する
  77. 77. Main9 List<Person>から ソース Personの名前を 中間操作 ,区切りで連結する 終端操作
  78. 78. 79 Collectors#joining ● joining() ● joining(delimiter) ● joining(delimiter, prefix, suffix) – 文字列の連結をするCollectorを返す – 単なる連結だけでなく,デリミタなども指定可
  79. 79. Main10 同じ値でグループ化
  80. 80. Main10 List<People>から 同じ性別でPeopleをグループ化 List<People>から 同じ名字でPeopleの名前をグループ化
  81. 81. 82 Collectors#groupingBy ● groupingBy(T -> K) – Kの同じ値でグループ化 – Map<K, List<T>>にする
  82. 82. 83 Collectors#groupingBy ● groupingBy(T -> K, Collector) – 第二引数はMapの値へのCollector – groupingBy(..., toSet()) : Map<K, Set<T>>
  83. 83. 84 Collectors#mapping ● mapping(T -> U, Collector) – 値の変換を行って集約するCollector
  84. 84. Main10_1 並列グループ化
  85. 85. groupingBy vs. groupingByConcurrent ● groupingByでも並列化できる – 分割統治法 – Map<K, List<V>>同士の連結が起きる ● 逐次よりも遅くなる可能性 ● groupingByConcurrent – 一つのMap<K, List<V>>にマルチスレッドでアクセス – 中間操作は並列 ● 中間操作があれば逐次よりも高速に ● どちらが良いかは,場合による
  86. 86. 87 Parallel groupingBy H e l l o , W o r l d !
  87. 87. 88 Parallel groupingBy Split!!
  88. 88. 89 Parallel groupingBy Map Map Map Map
  89. 89. 90 Parallel groupingBy Map Map Map MapMap Map
  90. 90. 91 Parallel groupingBy Map MapMap Map
  91. 91. 92 Parallel groupingBy Map Map
  92. 92. 93 H e l o , W o r l d ! Map parallel groupingByConcurrent
  93. 93. Any question?
  • hiromix222

    Sep. 10, 2016
  • kyamane13

    Sep. 4, 2016
  • nilfigo

    Sep. 3, 2016
  • gishi

    Aug. 21, 2015
  • ssuser1b7f9a

    Aug. 19, 2015

きつねさんと学ぶ Lambda式&StreamAPIハンズオン

Views

Total views

1,270

On Slideshare

0

From embeds

0

Number of embeds

35

Actions

Downloads

4

Shares

0

Comments

0

Likes

5

×