Ce diaporama a bien été signalé.
Nous utilisons votre profil LinkedIn et vos données d’activité pour vous proposer des publicités personnalisées et pertinentes. Vous pouvez changer vos préférences de publicités à tout moment.
1 / 54
Java8基礎勉強会
ラムダ式とストリームAPI
2014年3月25日
アリエル・ネットワーク 池添
2 / 54
本日のテーマ
3 / 54
for文を駆逐してやる!
この世から1つ残らず!
4 / 54
目次
• 概要
• ラムダ式の基礎
• ストリームAPIの基礎
• ストリームAPIの拡張
5 / 54
ラムダ式とストリームAPI
• ラムダ式とは関数を簡便に表現するための記法。
• ストリームAPIは、ラムダ式を利用したコレク
ション操作用のAPI
• 関数型プログラミング言語由来。歴史は古い。
• これまでの手続き型やオブジェ...
6 / 54
簡単なサンプル
• フルーツの一覧の中から
• 名前が“りんご”で始まり、
• 値段が100円以上のものを、
• 値段順で並び替え、
• 名前だけを取り出して、
• リストを作成する
1 List<String> apples =...
7 / 54
メリット
• 手続き的だった記述が宣言的になる
• 保守性の向上…?
• 可読性の向上…?
• 簡単に並列実行できるようになる
8 / 54
保守性が向上する?
データの取
得
データの取
得
条件による
抽出
条件による
抽出
データの加
工
データの加
工
コンテナへ
の登録
コンテナへ
の登録
for文for文
デー
タの
初期
化
デー
タの
取得
条件による抽...
9 / 54
可読性は?
• 野球選手の一覧から、チームごとの投手の平均
年俸を取得する処理の例。
1 Map<String, Double> m = players.stream()
2 .collect(Collectors.groupin...
10 / 54
ラムダ式の基礎
11 / 54
むかしばなし
Javaでdelegate型を扱えるようにしたで!
J++って言いますねん。
互換性のないものはJavaとは呼べません。
提訴します!
なんとまあセンスの悪い言語設計でしょう。
まともな言語設計者ならポリシーが
許...
12 / 54
なぜラムダ式が必要になったのか
• 非同期処理や並列処理が当たり前に使われるよ
うになり、ラムダ式の必要性が高まった。
• Microsoftの提案を受け入れていれば、ラムダ
式がもっと早く入っていたかもしれない。
• でも、1...
13 / 54
ラムダ式
• 関数を第一級オブジェクトとして扱えるように
なった。
• JVMで関数を直接扱えるようになったわけでは
なく、内部的にはクラスのインスタンスを使っ
て表現している。
14 / 54
ラムダ式の書き方
() -> 123
x -> x * x
(x, y) -> x + y
(int x, int y) -> {
return x + y;
}
いろいろ省略できる!
仮引数や戻り値の型はほとんど
型推論してく...
15 / 54
ラムダ式の使い方
• ラムダ式を渡される側
void hoge(Function<Integer, Integer> func) {
Integer ret = func.apply(42);
}
• ラムダ式を渡す側
hoge...
16 / 54
関数型インタフェース
• ラムダ式の型は関数型インタフェースで表現さ
れる。
• 関数型インタフェースとは
• 実装するべきメソッドを1つだけ持ってる
interface
• @FunctionalInterfaceアノテーショ...
17 / 54
標準の関数型インタフェース
• Runnable, Consumer, Function, Predicate,Supplier
• BiConsumer,BiFunction,BiPredicate
• BooleanSupp...
18 / 54
代表的な関数型インタフェース
• Runnable: 引数なし、戻り値なし
• Consumer: 引数1つ、戻り値なし
• Function: 引数1つ、戻り値あり
• Predicate: 引数1つ、戻り値がboolean
...
19 / 54
無名内部クラスとラムダ式の違い
無名内部クラス ラムダ式
外部変数へのアクセス 実質的なfinalの変
数のみアクセス可能。
実質的なfinalの変数のみ
アクセス可能。
エンクロージングイン
スタンスの参照
必ず持っている。 ...
20 / 54
Javaのラムダ式はクロージャではない
• ローカル変数は、実質的にfinalな変数にしか
アクセスできない。
• 独自のスコープは持たず、外のスコープを引き
継ぐ。
• エンクロージングインスタンスの参照は、基本
持たない。
21 / 54
ラムダ式のスコープ
class Outer {
public void func() {
final int a = 0;
int b = 1;
list.stream().forEach(x -> {
int a = 2;
S...
22 / 54
例外は苦手かも
• ラムダ式からチェック例外のあるAPIを呼び出す
場合
• 関数型インタフェースの定義にthrowsを記述する
(標準の関数型インタフェースにはついてない)
• ラムダ式の中でtry-catchを書く
list...
23 / 54
メソッド参照
• ラムダ式だけでなく、既存のメソッドも関数型
インタフェースで受け取ることが可能。
// ラムダ式を使った場合
list.forEach(x -> System.out.println(x));
// メソッド参...
24 / 54
Lambda Expression Deep Dive
• ラムダ式は無名内部クラスのシンタックスシュガーじゃな
い。
• コンパイル時ではなく実行時にクラスが生成される。
• invokeDynamic命令を使っている。
• ...
25 / 54
ラムダ式のバイトコード
INVOKEDYNAMIC apply()Ljava/util/function/IntFunction; [
// handle kind 0x6 : INVOKESTATIC
java/lang/in...
26 / 54
ラムダ式の実行時の挙動
Main.classMain.class
コンパイル時に
生成されるもの
invoke dynamicinvoke dynamic
static method
lambda$main$0
static m...
27 / 54
なぜこんな複雑なことを?
• コンパイル時にクラスを大量につくると、クラ
スロードのときに遅くなるかもしれないから。
とくにストリームAPIではラムダ式を大量につ
かうので。
• invokeDynamicを使うとパフォーマンス...
28 / 54
ストリームAPIの基礎
29 / 54
ストリームAPIとは
• パイプライン型のデータ処理のAPI
• 絞り込み、データ変換、グループ化、集計など
の操作をそれぞれ分離した形で記述できる。
• 絞り込みの条件や、加工方法などをラムダ式で
指定する。
• メソッドチェ...
30 / 54
ストリームパイプライン
• ストリームパイプラインの構成要素
• ソース(Source)
• 中間操作(Intermediate Operation)
• 終端操作(Terminal Operation)
• ストリームパイプラ...
31 / 54
サンプル
• 1行目がソース
• 2行目から5行目までが中間操作
• 6行目が終端操作
1 List<String> apples = fruits.stream()
2 .filter(f -> f.getName().sta...
32 / 54
ストリームパイプラインの挙動
中間
操作
中間
操作
中間
操作
結果
filterの条件に
一致しなければ
以降の処理は実
行しない
ソースの要素を
1つずつ中間操作
に流す
終端操作を呼び出したときに
初めて全体の処理が動く...
33 / 54
ソース
• 既存のデータからStream型のオブジェクトを
つくる。
• Streamの種類
• Stream<T>
• IntStream, LongStream, DoubleStream
• つくりかた
• Collect...
34 / 54
ソースの特性
• Sequential, Parallel
• 逐次実行か、並列実行か。
• Stream#parallelとStream#sequentialで相互に
変換可能。
• Ordered, Unordered
• ...
35 / 54
中間操作
• 絞り込みや写像などの操作を指定して、新しい
Streamを返す。
• 遅延実行
• 処理方法を指定するだけで、実際には処理しない。
• 中間操作を呼び出すたびにループしてたら効率が悪い。
終端操作が呼ばれたときに、...
36 / 54
特殊な中間操作
• ステートフルな中間操作:distinct, sorted
• 中間操作は基本的にステートレスだが、ステートフ
ルなものもある。
• 無限リストや並列処理のときに注意が必要。
• ショートサーキット評価な中間操...
37 / 54
終端操作
• ストリームパイプラインを実行して、なんらか
の結果を取得する処理。
forEachだけは戻り値を返さない。副作用専用
のメソッド。
• 処理の種類
• たたみ込み:collect, reduce
• 集計:min,...
38 / 54
汎用的な終端操作:collect
• 引数にCollectorを指定して様々な処理がおこなえる。
• 集計:
• averagingInt, averagingLong, averagingDouble
• summingInt...
39 / 54
Optionalを返す終端操作
• Optional
• nullチェックめんどくさい・・・。パイプラインの途
中でnullが現れると流れが止まってしまう。
• nullを駆逐し(ry
• Java8ではOptional型が入っ...
40 / 54
ショートサーキット評価の終端操作
• ショートサーキット評価をする終端操作
• anyMatch, allMatch, noneMatch, findFirst,
findAny
• 例えば、Stream#countは全要素をル...
41 / 54
並列処理
• すごく簡単に並列化できる。ソースを生成するときに、
Collection#parallelStreamや, Stream#parallel
を使うだけ。
• 順序保証
• ソースがORDEREDであれば並列実行して...
42 / 54
並列処理のやりかた
• parallel()をつけるだけ!
• ただし、上記のような例ではあまり並列処理の
うまみはない。
1 List<String> apples = fruits.stream().parallel()
2...
43 / 54
並列処理の挙動
中間
操作
中間
操作
中間
操作
結果 43
分割したソースごとに
異なるスレッドで中間
操作を並列に実行
ソースを複数に分割
spliterator
順序を保証する
場合は内部で
バッファリング
中間
操作
...
44 / 54
ストリームAPIの拡張
45 / 54
ストリームAPIは機能不足?
• なんかいろいろ足りない!
• 他の言語と比べて標準で用意されてる機能が少ない。
• 複数のStreamを合成するzipすらないなんて…
• 毎回stream()を呼ぶのめんどくさい…
• 足りな...
46 / 54
ストリームAPIの拡張ポイント
• たたみ込みを使えばたいていの処理はつくれる。
• 汎用的なCollectorをつくって、再利用できる
ようにしておくとよさそう。
• CollectorをつくるためのヘルパーAPIが用意
され...
47 / 54
Collectorの構成要素
• supplier
• コンテナの初期値を生成する人
• accumulator
• 値を加工してコンテナに格納する人
• combiner
• 並列で実行された場合、コンテナを結合する人
• f...
48 / 54
Collectorの動き
コンテナコンテナ コンテナコンテナ
コンテナコンテナ
結果結果
supplier supplier
combiner
finisher
accumulator accumulator
並列的にデータがや...
49 / 54
Collectorのつくり方
• Collector.of
• supplier, accumulator, combiner, finisher
を指定して新しいCollectorをつくる
• Collectors.mapMe...
50 / 54
Collectorを使った例
• チームごとの投手の平均年俸を取得する
• 2つのCollectorを用意
• グループ化したストリームを返すCollector
• グループごとの平均値を返すCollector
1 Map<St...
51 / 54
Collectorの実装
1 static <T, V> Collector<Entry<V, List<T>>, ?, Map<V, Double>>
2 averagePerGroupCollector(ToIntFunct...
52 / 54
まとめ
• ラムダ式
• 関数を簡便に表記するための記法。
• デメリットも少ないし使わない手はないよね。
• ストリームAPI
• 慣れるまでは読み書きも難しいし、変なバグを生み
やすいかもしれない。
• でも慣れると少ない記...
53 / 54
おまけ
• Java8を使うときはIntelliJ IDEAがおすすめ。
(EclipseのJava8正式対応は2014年6月)
• Java8の文法にもしっかり対応(たまーに型推
論間違えたりするけど)
• 無名内部クラスを書...
54 / 54
参考
• JavaのLambdaの裏事情
• http://www.slideshare.net/nowokay/java-2898601
• ラムダと invokedynamic の蜜月
• http://www.slides...
Prochain SlideShare
Chargement dans…5
×

社内Java8勉強会 ラムダ式とストリームAPI

50 378 vues

Publié le

  • DOWNLOAD THIS BOOKS INTO AVAILABLE FORMAT (Unlimited) ......................................................................................................................... ......................................................................................................................... Download Full PDF EBOOK here { http://bit.ly/2m77EgH } ......................................................................................................................... Download Full EPUB Ebook here { http://bit.ly/2m77EgH } ......................................................................................................................... ACCESS WEBSITE for All Ebooks ......................................................................................................................... Download Full PDF EBOOK here { http://bit.ly/2m77EgH } ......................................................................................................................... Download EPUB Ebook here { http://bit.ly/2m77EgH } ......................................................................................................................... Download doc Ebook here { http://bit.ly/2m77EgH } ......................................................................................................................... ......................................................................................................................... ......................................................................................................................... .............. Browse by Genre Available eBooks ......................................................................................................................... Art, Biography, Business, Chick Lit, Children's, Christian, Classics, Comics, Contemporary, Cookbooks, Crime, Ebooks, Fantasy, Fiction, Graphic Novels, Historical Fiction, History, Horror, Humor And Comedy, Manga, Memoir, Music, Mystery, Non Fiction, Paranormal, Philosophy, Poetry, Psychology, Religion, Romance, Science, Science Fiction, Self Help, Suspense, Spirituality, Sports, Thriller, Travel, Young Adult,
       Répondre 
    Voulez-vous vraiment ?  Oui  Non
    Votre message apparaîtra ici
  • DOWNLOAD THIS BOOKS INTO AVAILABLE FORMAT (Unlimited) ......................................................................................................................... ......................................................................................................................... Download Full PDF EBOOK here { http://bit.ly/2m77EgH } ......................................................................................................................... Download Full EPUB Ebook here { http://bit.ly/2m77EgH } ......................................................................................................................... ACCESS WEBSITE for All Ebooks ......................................................................................................................... Download Full PDF EBOOK here { http://bit.ly/2m77EgH } ......................................................................................................................... Download EPUB Ebook here { http://bit.ly/2m77EgH } ......................................................................................................................... Download doc Ebook here { http://bit.ly/2m77EgH } ......................................................................................................................... ......................................................................................................................... ......................................................................................................................... .............. Browse by Genre Available eBooks ......................................................................................................................... Art, Biography, Business, Chick Lit, Children's, Christian, Classics, Comics, Contemporary, Cookbooks, Crime, Ebooks, Fantasy, Fiction, Graphic Novels, Historical Fiction, History, Horror, Humor And Comedy, Manga, Memoir, Music, Mystery, Non Fiction, Paranormal, Philosophy, Poetry, Psychology, Religion, Romance, Science, Science Fiction, Self Help, Suspense, Spirituality, Sports, Thriller, Travel, Young Adult,
       Répondre 
    Voulez-vous vraiment ?  Oui  Non
    Votre message apparaîtra ici
  • DOWNLOAD THIS BOOKS INTO AVAILABLE FORMAT (Unlimited) ......................................................................................................................... ......................................................................................................................... Download Full PDF EBOOK here { https://tinyurl.com/y6a5rkg5 } ......................................................................................................................... Download Full EPUB Ebook here { https://tinyurl.com/y6a5rkg5 } ......................................................................................................................... ACCESS WEBSITE for All Ebooks ......................................................................................................................... Download Full PDF EBOOK here { https://tinyurl.com/y6a5rkg5 } ......................................................................................................................... Download EPUB Ebook here { https://tinyurl.com/y6a5rkg5 } ......................................................................................................................... Download doc Ebook here { https://tinyurl.com/y6a5rkg5 } ......................................................................................................................... ......................................................................................................................... ......................................................................................................................... .............. Browse by Genre Available eBooks ......................................................................................................................... Art, Biography, Business, Chick Lit, Children's, Christian, Classics, Comics, Contemporary, Cookbooks, Crime, Ebooks, Fantasy, Fiction, Graphic Novels, Historical Fiction, History, Horror, Humor And Comedy, Manga, Memoir, Music, Mystery, Non Fiction, Paranormal, Philosophy, Poetry, Psychology, Religion, Romance, Science, Science Fiction, Self Help, Suspense, Spirituality, Sports, Thriller, Travel, Young Adult,
       Répondre 
    Voulez-vous vraiment ?  Oui  Non
    Votre message apparaîtra ici
  • DOWNLOAD THIS BOOKS INTO AVAILABLE FORMAT (Unlimited) ......................................................................................................................... ......................................................................................................................... Download Full PDF EBOOK here { http://bit.ly/2m77EgH } ......................................................................................................................... Download Full EPUB Ebook here { http://bit.ly/2m77EgH } ......................................................................................................................... ACCESS WEBSITE for All Ebooks ......................................................................................................................... Download Full PDF EBOOK here { http://bit.ly/2m77EgH } ......................................................................................................................... Download EPUB Ebook here { http://bit.ly/2m77EgH } ......................................................................................................................... Download doc Ebook here { http://bit.ly/2m77EgH } ......................................................................................................................... ......................................................................................................................... ......................................................................................................................... .............. Browse by Genre Available eBooks ......................................................................................................................... Art, Biography, Business, Chick Lit, Children's, Christian, Classics, Comics, Contemporary, Cookbooks, Crime, Ebooks, Fantasy, Fiction, Graphic Novels, Historical Fiction, History, Horror, Humor And Comedy, Manga, Memoir, Music, Mystery, Non Fiction, Paranormal, Philosophy, Poetry, Psychology, Religion, Romance, Science, Science Fiction, Self Help, Suspense, Spirituality, Sports, Thriller, Travel, Young Adult,
       Répondre 
    Voulez-vous vraiment ?  Oui  Non
    Votre message apparaîtra ici
  • DOWNLOAD THIS BOOKS INTO AVAILABLE FORMAT (Unlimited) ......................................................................................................................... ......................................................................................................................... Download Full PDF EBOOK here { https://tinyurl.com/y6a5rkg5 } ......................................................................................................................... Download Full EPUB Ebook here { https://tinyurl.com/y6a5rkg5 } ......................................................................................................................... ACCESS WEBSITE for All Ebooks ......................................................................................................................... Download Full PDF EBOOK here { https://tinyurl.com/y6a5rkg5 } ......................................................................................................................... Download EPUB Ebook here { https://tinyurl.com/y6a5rkg5 } ......................................................................................................................... Download doc Ebook here { https://tinyurl.com/y6a5rkg5 } ......................................................................................................................... ......................................................................................................................... ......................................................................................................................... .............. Browse by Genre Available eBooks ......................................................................................................................... Art, Biography, Business, Chick Lit, Children's, Christian, Classics, Comics, Contemporary, Cookbooks, Crime, Ebooks, Fantasy, Fiction, Graphic Novels, Historical Fiction, History, Horror, Humor And Comedy, Manga, Memoir, Music, Mystery, Non Fiction, Paranormal, Philosophy, Poetry, Psychology, Religion, Romance, Science, Science Fiction, Self Help, Suspense, Spirituality, Sports, Thriller, Travel, Young Adult,
       Répondre 
    Voulez-vous vraiment ?  Oui  Non
    Votre message apparaîtra ici

社内Java8勉強会 ラムダ式とストリームAPI

  1. 1. 1 / 54 Java8基礎勉強会 ラムダ式とストリームAPI 2014年3月25日 アリエル・ネットワーク 池添
  2. 2. 2 / 54 本日のテーマ
  3. 3. 3 / 54 for文を駆逐してやる! この世から1つ残らず!
  4. 4. 4 / 54 目次 • 概要 • ラムダ式の基礎 • ストリームAPIの基礎 • ストリームAPIの拡張
  5. 5. 5 / 54 ラムダ式とストリームAPI • ラムダ式とは関数を簡便に表現するための記法。 • ストリームAPIは、ラムダ式を利用したコレク ション操作用のAPI • 関数型プログラミング言語由来。歴史は古い。 • これまでの手続き型やオブジェクト指向的なプ ログラミング手法から、関数型プログラミング に変わります。 • パラダイムシフトのよかん!!
  6. 6. 6 / 54 簡単なサンプル • フルーツの一覧の中から • 名前が“りんご”で始まり、 • 値段が100円以上のものを、 • 値段順で並び替え、 • 名前だけを取り出して、 • リストを作成する 1 List<String> apples = fruits.stream() 2 .filter(f -> f.getName().startsWith("りんご")) 3 .filter(f -> f.getPrice() > 100) 4 .sorted(Comparator.comparingInt(Fruit::getPrice)) 5 .map(Fruit::getName) 6 .collect(Collectors.toList());
  7. 7. 7 / 54 メリット • 手続き的だった記述が宣言的になる • 保守性の向上…? • 可読性の向上…? • 簡単に並列実行できるようになる
  8. 8. 8 / 54 保守性が向上する? データの取 得 データの取 得 条件による 抽出 条件による 抽出 データの加 工 データの加 工 コンテナへ の登録 コンテナへ の登録 for文for文 デー タの 初期 化 デー タの 取得 条件による抽出条件による抽出 データの加工 コンテナへの 登録 \ ごちゃっ / パイプライン的ですっきり • 処理の追加・削除・順番の入れ替えなどがやり やすい。 • 再利用性やテスタビリティも向上するかも。
  9. 9. 9 / 54 可読性は? • 野球選手の一覧から、チームごとの投手の平均 年俸を取得する処理の例。 1 Map<String, Double> m = players.stream() 2 .collect(Collectors.groupingBy(player -> player.getTeam())) 3 .entrySet() 4 .stream() 5 .collect(Collectors.toMap( 6 entry -> entry.getKey(), 7 entry -> entry.getValue().stream() 8 .filter(player -> player.getPosition().equals("投手")) 9 .mapToInt(player -> player.getSalary()) 10 .average() 11 .orElse(0) 12 ) 13 ); • 気をつけないとすぐに読みにくくなる。 • stream()とかstream()とかstream()とかノイズが多い。
  10. 10. 10 / 54 ラムダ式の基礎
  11. 11. 11 / 54 むかしばなし Javaでdelegate型を扱えるようにしたで! J++って言いますねん。 互換性のないものはJavaとは呼べません。 提訴します! なんとまあセンスの悪い言語設計でしょう。 まともな言語設計者ならポリシーが 許さないと思います。 じゃあ、自分らで言語つくりますわ。 C#って言うやつ。 1997年 1998年 2000年 delegateをラムダ式で書けるようにしたで。 2005年 Microsoft Sun 某研究者
  12. 12. 12 / 54 なぜラムダ式が必要になったのか • 非同期処理や並列処理が当たり前に使われるよ うになり、ラムダ式の必要性が高まった。 • Microsoftの提案を受け入れていれば、ラムダ 式がもっと早く入っていたかもしれない。 • でも、15年も先を見越して言語設計するなん てことは難しい。
  13. 13. 13 / 54 ラムダ式 • 関数を第一級オブジェクトとして扱えるように なった。 • JVMで関数を直接扱えるようになったわけでは なく、内部的にはクラスのインスタンスを使っ て表現している。
  14. 14. 14 / 54 ラムダ式の書き方 () -> 123 x -> x * x (x, y) -> x + y (int x, int y) -> { return x + y; } いろいろ省略できる! 仮引数や戻り値の型はほとんど 型推論してくれる。かしこい!
  15. 15. 15 / 54 ラムダ式の使い方 • ラムダ式を渡される側 void hoge(Function<Integer, Integer> func) { Integer ret = func.apply(42); } • ラムダ式を渡す側 hoge(x -> x * x); 関数型インタフェース
  16. 16. 16 / 54 関数型インタフェース • ラムダ式の型は関数型インタフェースで表現さ れる。 • 関数型インタフェースとは • 実装するべきメソッドを1つだけ持ってる interface • @FunctionalInterfaceアノテーションを付ける と、コンパイル時にメソッドが1つだけかどうか チェックしてくれる。つけなくてもよい。 @FunctionalInterface public interface Function<T, R> { R apply(T t); }
  17. 17. 17 / 54 標準の関数型インタフェース • Runnable, Consumer, Function, Predicate,Supplier • BiConsumer,BiFunction,BiPredicate • BooleanSupplier • IntBinaryOperator,IntConsumer,IntFunction,IntPre dicate,IntSupplier,IntToDoubleFunction,IntToLong Function,IntUnaryOperator,ObjIntConsumer,ToIntBi Function,ToIntFunction • LongBinaryOperator,LongConsumer,LongFunction,Lon gPredicate,LongSupplier,LongToDoubleFunction,Lon gToIntFunction,LongUnaryOperator,ObjLongConsumer ,ToLongBiFunction,ToLongFunction • DoubleBinaryOperator,DoubleConsumer,DoubleFuncti on,DoublePredicate,DoubleSupplier,DoubleToIntFun ction,DoubleToLongFunction,DoubleUnaryOperator,O bjDoubleConsumer,ToDoubleBiFunction,ToDoubleFunc tion
  18. 18. 18 / 54 代表的な関数型インタフェース • Runnable: 引数なし、戻り値なし • Consumer: 引数1つ、戻り値なし • Function: 引数1つ、戻り値あり • Predicate: 引数1つ、戻り値がboolean • Supplier: 引数なし、戻り値あり • Bi + Xxxxx: 引数が2つ
  19. 19. 19 / 54 無名内部クラスとラムダ式の違い 無名内部クラス ラムダ式 外部変数へのアクセス 実質的なfinalの変 数のみアクセス可能。 実質的なfinalの変数のみ アクセス可能。 エンクロージングイン スタンスの参照 必ず持っている。 必要がなければ持たない。 メモリリークがおきにくい。 クラスファイルの生成 コンパイル時にクラ スが生成される。 実行時にクラスが生成され る。 クラスのロード時間が短縮 されるかも。 インスタンスの生成 明示的にnewする。 JVMが最適な生成方法を選 択する。
  20. 20. 20 / 54 Javaのラムダ式はクロージャではない • ローカル変数は、実質的にfinalな変数にしか アクセスできない。 • 独自のスコープは持たず、外のスコープを引き 継ぐ。 • エンクロージングインスタンスの参照は、基本 持たない。
  21. 21. 21 / 54 ラムダ式のスコープ class Outer { public void func() { final int a = 0; int b = 1; list.stream().forEach(x -> { int a = 2; System.out.println(b); }); b = 3; } } 値の変更が行われるローカル 変数はアクセス不可 独自のスコープを持たな いので、変数名の衝突が 起きる。 明示しなければ、エンクロー ジングインスタンスの参照を 持たない。
  22. 22. 22 / 54 例外は苦手かも • ラムダ式からチェック例外のあるAPIを呼び出す 場合 • 関数型インタフェースの定義にthrowsを記述する (標準の関数型インタフェースにはついてない) • ラムダ式の中でtry-catchを書く list.map(x -> { try { // チェック例外のある呼び出し } catch(XxxException ex) { // エラー処理。 } }).collect(Collectors.toList());
  23. 23. 23 / 54 メソッド参照 • ラムダ式だけでなく、既存のメソッドも関数型 インタフェースで受け取ることが可能。 // ラムダ式を使った場合 list.forEach(x -> System.out.println(x)); // メソッド参照を使った場合 list.forEach(System.out::println); fruits.map(fruit -> fruit.getName()); // インスタンスメソッドの参照もOK fruits.map(Fruit::getName);
  24. 24. 24 / 54 Lambda Expression Deep Dive • ラムダ式は無名内部クラスのシンタックスシュガーじゃな い。 • コンパイル時ではなく実行時にクラスが生成される。 • invokeDynamic命令を使っている。 • ラムダ式をコンパイルするとどんなバイトコードが生成さ れるかみてみよう。 対象のコードはこんな感じ public class Main { public void main(){ Sample sample = new Sample(); sample.func(x -> x * x); } }
  25. 25. 25 / 54 ラムダ式のバイトコード INVOKEDYNAMIC apply()Ljava/util/function/IntFunction; [ // handle kind 0x6 : INVOKESTATIC java/lang/invoke/LambdaMetafactory.metafactory() // arguments: (I)Ljava/lang/Object;.class, // handle kind 0x6 : INVOKESTATIC Main.lambda$main$0((I)Ljava/lang/Integer;) , (I)Ljava/lang/Integer;.class ] BIPUSH 12 INVOKEVIRTUAL Sample.func (Ljava/util/function/IntFunction;I)I // ・・・途中省略・・・ private static lambda$main$0(I)Ljava/lang/Integer; L0 // ラムダ式の中の処理 x -> x * x ラムダのオブジェクトをスタックに積んで メソッドを呼び出す ラムダ式の オブジェクト をつくる命令 ラムダ式の なかみ
  26. 26. 26 / 54 ラムダ式の実行時の挙動 Main.classMain.class コンパイル時に 生成されるもの invoke dynamicinvoke dynamic static method lambda$main$0 static method lambda$main$0 LambdaMetafactory #metafactory LambdaMetafactory #metafactory ラムダのインス タンスをつくる メソッド ラムダのインス タンスをつくる メソッド class Lambda$1 関数型インタフェー スを実装 lambda$main$0 を呼び出す class Lambda$1 関数型インタフェー スを実装 lambda$main$0 を呼び出す JVMの中のクラス 実行時に作られるもの 1回目の呼び出し (ブートストラップ) 2回目以降 の呼び出し (Method Handle) 作成 Mainの内部クラス として作成 new
  27. 27. 27 / 54 なぜこんな複雑なことを? • コンパイル時にクラスを大量につくると、クラ スロードのときに遅くなるかもしれないから。 とくにストリームAPIではラムダ式を大量につ かうので。 • invokeDynamicを使うとパフォーマンスをあ まり落とさず動的な処理が実現できる。 • 今後JVMの実装が変わると、インスタンスの生 成方法がより効率的なものになるかも。
  28. 28. 28 / 54 ストリームAPIの基礎
  29. 29. 29 / 54 ストリームAPIとは • パイプライン型のデータ処理のAPI • 絞り込み、データ変換、グループ化、集計など の操作をそれぞれ分離した形で記述できる。 • 絞り込みの条件や、加工方法などをラムダ式で 指定する。 • メソッドチェイン形式で記述できる。
  30. 30. 30 / 54 ストリームパイプライン • ストリームパイプラインの構成要素 • ソース(Source) • 中間操作(Intermediate Operation) • 終端操作(Terminal Operation) • ストリームパイプラインは、1つ以上のソース、 0個以上の中間操作、1つの終端操作から構成 される。 • 1つのStreamに対して複数の終端操作(いわゆ る分配)をおこなってはいけない。 • 終端操作の結果をソースとして処理を継続する ことも可能。
  31. 31. 31 / 54 サンプル • 1行目がソース • 2行目から5行目までが中間操作 • 6行目が終端操作 1 List<String> apples = fruits.stream() 2 .filter(f -> f.getName().startsWith("りんご")) 3 .filter(f -> f.getPrice() > 100) 4 .sorted(Comparator.comparingInt(Fruit::getPrice)) 5 .map(Fruit::getName) 6 .collect(Collectors.toList());
  32. 32. 32 / 54 ストリームパイプラインの挙動 中間 操作 中間 操作 中間 操作 結果 filterの条件に 一致しなければ 以降の処理は実 行しない ソースの要素を 1つずつ中間操作 に流す 終端操作を呼び出したときに 初めて全体の処理が動く。 それまで中間操作は実行され ない。 ソース 終端操作 を実行
  33. 33. 33 / 54 ソース • 既存のデータからStream型のオブジェクトを つくる。 • Streamの種類 • Stream<T> • IntStream, LongStream, DoubleStream • つくりかた • Collection#stream • Arrays#stream • Stream#of • BufferReader#lines • IntStream#range
  34. 34. 34 / 54 ソースの特性 • Sequential, Parallel • 逐次実行か、並列実行か。 • Stream#parallelとStream#sequentialで相互に 変換可能。 • Ordered, Unordered • Listや配列などはOrdered, SetなどはUnordered • Stream#unorderedで順序を保証しないStreamに 変換可能。 • 無限リスト
  35. 35. 35 / 54 中間操作 • 絞り込みや写像などの操作を指定して、新しい Streamを返す。 • 遅延実行 • 処理方法を指定するだけで、実際には処理しない。 • 中間操作を呼び出すたびにループしてたら効率が悪い。 終端操作が呼ばれたときに、複数の中間操作をまとめて ループ処理。 • 処理の種類 • 絞り込み: filter • 写像: map, flatMap • 並び替え: sorted • 数の制御: limit, skip • 同一要素除外: distinct • tee的なもの: peek
  36. 36. 36 / 54 特殊な中間操作 • ステートフルな中間操作:distinct, sorted • 中間操作は基本的にステートレスだが、ステートフ ルなものもある。 • 無限リストや並列処理のときに注意が必要。 • ショートサーキット評価な中間操作:limit • 指定された数の要素を流したら処理を打ち切る。 • 無限Streamを有限Streamにしてくれる。 • 副作用向け中間操作:peek • 中間操作では基本的に副作用するべきでない。 • デバッグやログ出力用途以外にはなるべく使わない ようにしよう。
  37. 37. 37 / 54 終端操作 • ストリームパイプラインを実行して、なんらか の結果を取得する処理。 forEachだけは戻り値を返さない。副作用専用 のメソッド。 • 処理の種類 • たたみ込み:collect, reduce • 集計:min, max, average, sum, count • 単一の値の取得:findFirst, findAny • 条件:allMatch, anyMatch, noneMatch • 繰り返し:forEach, forEachOrdered
  38. 38. 38 / 54 汎用的な終端操作:collect • 引数にCollectorを指定して様々な処理がおこなえる。 • 集計: • averagingInt, averagingLong, averagingDouble • summingInt, summingLong, summingDouble • counting • maxBy, minBy • summarizing • グループ化 • groupingBy, partitioningBy • コンテナに累積 • toList, toMap, toSet • 結合 • joining • たたみ込み • reducing
  39. 39. 39 / 54 Optionalを返す終端操作 • Optional • nullチェックめんどくさい・・・。パイプラインの途 中でnullが現れると流れが止まってしまう。 • nullを駆逐し(ry • Java8ではOptional型が入った。 • Stream APIの中にはOptionalを返す終端操作 がある。 • min, max, average, sum, findFirst, findAny, reduceなど。 • 空のリストに対してこれらの処理を呼び出すと Optional.emptyを返す。
  40. 40. 40 / 54 ショートサーキット評価の終端操作 • ショートサーキット評価をする終端操作 • anyMatch, allMatch, noneMatch, findFirst, findAny • 例えば、Stream#countは全要素をループで回 すので時間がかかるが、Stream#findAnyは ショートサーキット評価なので、1つめの要素 が見つかればすぐに終わる。 if(stream.count() != 0) if(stream.findAny().isPresent())
  41. 41. 41 / 54 並列処理 • すごく簡単に並列化できる。ソースを生成するときに、 Collection#parallelStreamや, Stream#parallel を使うだけ。 • 順序保証 • ソースがORDEREDであれば並列実行しても順番は保証される。 • ただし、順序を保つために内部にバッファリングするので、 あまりパフォーマンスはよくない。 • 順番を気にしないのであれば、unorderedすると効率がよく なる。 • 副作用に注意 • 中間操作で副作用が生じる場合はちゃんとロックしよう。 • ただし、ロックすると並列で実行しても待ちが多くなるので、 パフォーマンスはよくない。 • スレッドセーフでないArrayListなども並列実行可能。
  42. 42. 42 / 54 並列処理のやりかた • parallel()をつけるだけ! • ただし、上記のような例ではあまり並列処理の うまみはない。 1 List<String> apples = fruits.stream().parallel() 2 .filter(f -> f.getName().startsWith("りんご")) 3 .filter(f -> f.getPrice() > 100) 4 .sorted(Comparator.comparingInt(Fruit::getPrice)) 5 .map(Fruit::getName) 6 .collect(Collectors.toList());
  43. 43. 43 / 54 並列処理の挙動 中間 操作 中間 操作 中間 操作 結果 43 分割したソースごとに 異なるスレッドで中間 操作を並列に実行 ソースを複数に分割 spliterator 順序を保証する 場合は内部で バッファリング 中間 操作 中間 操作 中間 操作 複数スレッドの 実行結果を結合終端操作
  44. 44. 44 / 54 ストリームAPIの拡張
  45. 45. 45 / 54 ストリームAPIは機能不足? • なんかいろいろ足りない! • 他の言語と比べて標準で用意されてる機能が少ない。 • 複数のStreamを合成するzipすらないなんて… • 毎回stream()を呼ぶのめんどくさい… • 足りないならつくればいいじゃない。 • 関数型言語なら関数をどんどん増やせばよい。 C#なら拡張メソッドという仕組みがある。 • でも、JavaではStreamに自由にメソッドを増やせ ない!こまった!
  46. 46. 46 / 54 ストリームAPIの拡張ポイント • たたみ込みを使えばたいていの処理はつくれる。 • 汎用的なCollectorをつくって、再利用できる ようにしておくとよさそう。 • CollectorをつくるためのヘルパーAPIが用意 されている。既存のCollectorを組み合わせた り、一から新しい終端操作をつくったりするこ とができる。
  47. 47. 47 / 54 Collectorの構成要素 • supplier • コンテナの初期値を生成する人 • accumulator • 値を加工してコンテナに格納する人 • combiner • 並列で実行された場合、コンテナを結合する人 • finisher • 最後にコンテナを加工する人
  48. 48. 48 / 54 Collectorの動き コンテナコンテナ コンテナコンテナ コンテナコンテナ 結果結果 supplier supplier combiner finisher accumulator accumulator 並列的にデータがやってくる
  49. 49. 49 / 54 Collectorのつくり方 • Collector.of • supplier, accumulator, combiner, finisher を指定して新しいCollectorをつくる • Collectors.mapMerger • Collectorにcombinerを追加する • Collectors.mapping • accumulatorの前に実行される写像処理を追加す る • Collectors.collectingAndThen • Collectorにfinisherを追加する
  50. 50. 50 / 54 Collectorを使った例 • チームごとの投手の平均年俸を取得する • 2つのCollectorを用意 • グループ化したストリームを返すCollector • グループごとの平均値を返すCollector 1 Map<String, Double> averageSalaryMap = players.stream() 2 .filter(player -> player.getPosition().equals("投手")) 3 .collect(groupedStreamCollector(Player::getTeam)) 4 .collect(averagePerGroupCollector(Player::getSalary));
  51. 51. 51 / 54 Collectorの実装 1 static <T, V> Collector<Entry<V, List<T>>, ?, Map<V, Double>> 2 averagePerGroupCollector(ToIntFunction<T> mapper) { 3 return Collector.of( 4 () -> new HashMap<>(), 5 (map, entry) -> { 6 entry.getValue().stream() 7 .mapToInt(mapper) 8 .average() 9 .ifPresent(ave -> map.put(entry.getKey(), ave)); 10 }, 11 (left, right) -> { 12 left.putAll(right); 13 return left; 14 } 15 ); 16 } 17 static <T, K> Collector<T, ?, Stream<Entry<K, List<T>>>> 18 groupedStreamCollector(Function<T, ? extends K> mapper) { 19 return Collectors.collectingAndThen( 20 Collectors.groupingBy(mapper), map -> map.entrySet().stream()); 21 } accumulator combiner finisher • つくるのは難しいけど、汎用化しておけばいろ いろなところで使える。 supplier
  52. 52. 52 / 54 まとめ • ラムダ式 • 関数を簡便に表記するための記法。 • デメリットも少ないし使わない手はないよね。 • ストリームAPI • 慣れるまでは読み書きも難しいし、変なバグを生み やすいかもしれない。 • でも慣れると少ない記述で複雑な処理が実現できる。 そして何より書いていて楽しい! • しかし、標準で用意されてる機能が少ないのに、拡 張が難しいのはどうにかならんかね? • 今後はオレオレコレクションやStreamUtilsクラ スが乱立する可能性も!?
  53. 53. 53 / 54 おまけ • Java8を使うときはIntelliJ IDEAがおすすめ。 (EclipseのJava8正式対応は2014年6月) • Java8の文法にもしっかり対応(たまーに型推 論間違えたりするけど) • 無名内部クラスを書いてると、ラムダ式に書き 換えてくれる。 • for文を書いてると、ストリームAPIに書き換 えてくれる。(複雑な処理はムリだけど)
  54. 54. 54 / 54 参考 • JavaのLambdaの裏事情 • http://www.slideshare.net/nowokay/java-2898601 • ラムダと invokedynamic の蜜月 • http://www.slideshare.net/miyakawataku/lambda-meetsinvokedynamic • 倭マン's BLOG • http://waman.hatenablog.com/category/Java8 • ラムダ禁止について本気出して考えてみた - 9つのパターンで見る Stream API • http://acro-engineer.hatenablog.com/entry/2013/12/16/235900 • Collectorを征す者はStream APIを征す(部分的に) • http://blog.exoego.net/2013/12/control-collector-to-rule-stream- api.html • きしだのはてな • http://d.hatena.ne.jp/nowokay/searchdiary?word=%2A%5Bjava8%5D • 徹底解説!Project Lambdaのすべて returns • http://www.slideshare.net/bitter_fox/java8-launchJava • SE 8 lambdaで変わるプログラミングスタイル • http://pt.slideshare.net/nowokay/lambdajava-se-8-lambda

×