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.

【java8 勉強会】 怖くない!ラムダ式, Stream API

デーコムでは9月30日に職場でJava 8の勉強会を実施しました。その時の資料を公開しますので、ぜひJava 8の世界に触れてみてください。

■ 【java8 勉強会】 怖くない!ラムダ式, Stream API
http://www.dcom-web.co.jp/technology/java8study/ ‎
■ デーコムHP
http://www.dcom-web.co.jp/
■ デーコムFacebook
https://www.facebook.com/dcom.corp/

  • Be the first to comment

【java8 勉強会】 怖くない!ラムダ式, Stream API

  1. 1. Java 8 勉強会 怖くない!ラムダ式, Stream API 2015/09/30 株式会社デーコム Ken
  2. 2. 自己紹介  名前  Ken  所属  株式会社デーコム (4年目)  やってること  Webアプリの実装  Java, SAStruts  Javascript, CSS3  jQuery, flotr2(グラフ表示)  SPARQL (sqlっぽいやつ)  今熱いこと  数学, 哲学  『数学ガール』(結城浩) とか  コンピュータ将棋(電王戦)
  3. 3. 自己紹介 – つづき  趣味とか  趣味プログラミング(まれに)  なぞぷよ, 2chブラウザ, ルービックキューブ用タイマーなど  音ゲー  beatmaniaIIDX 全曲ハードクリア(未解禁曲以外)  Dance Dance Revolution 足鳳凰  Splatoon  ウデマエ S, 最近のブキ:ノヴァブラスターネオ  タイムアタック  ルービックキューブ (自己べ22秒, 最近は40秒)  海腹川背, 星のカービィSDX, ロックマンX4
  4. 4. 勉強会のtarget  Java 6,7の知識で止まっている方  ラムダ式、あぁあの 気持ち悪い やつね という方  StreamAPI、って何だ という方
  5. 5. Java 8の新機能のうち、今回話さないこと  話さないこと  Stream API の parallel()  (使ったことない & 排他など複雑なので)  Optional  (準備できませんでした)  DateTime API  デフォルトメソッド  など...
  6. 6. 前提知識  Java 6  interface  匿名クラス  ジェネリクス
  7. 7. ラムダ式 (Lambda Expression) 舎 λ λ λ λ.....
  8. 8. x -> x * 2
  9. 9. ラムダ式  x -> x * 2  x を引数に取って、x * 2 を返す  メソッドとして考えると  int convert(int x) { return x * 2; }  JavaScriptなら  function(x){ return x * 2; }
  10. 10. ありそうな例
  11. 11. ラムダ式 - ありそうな例  人を表すクラス  class Person { String name; int age; }
  12. 12. ラムダ式 - ありそうな例  20歳以上の人だけ処理する  public void main(){ method(list, 20); }  void method (List<Person> list, int minAge) { for(Person p : list) { if(p.age >= minAge) doSomething(p); } }
  13. 13. ラムダ式 - ありそうな例  6歳以上12歳以下の人だけを処理する  public void main(){ method(list, 6, 12); }  void method (List<Person> list, int minAge, int maxAge) { for(Person p : list) { if(p.age >= minAge && p.age <= maxAge) doSomething(p); } }
  14. 14. ラムダ式 - ありそうな例  名前が「A」で始まる人だけを処理する  public void main(){ method(list, 0, 999, “A”); }  void method (List<Person> list, int minAge, int maxAge, String nameStartWith) { for(Person p : list) { if(p.age >= minAge && p.age <= maxAge && p.name.startWith(nameStartWith)) doSomething(p); } }
  15. 15. ラムダ式 - ありそうな例  名前が「B」で終わる人だけを処理  年齢が偶数の人だけを処理  名前の文字数が10以上の人だけを処理 ・ ・ ・
  16. 16. _人人人人人人_ > 引数地獄 <  ̄Y^Y^Y^Y^Y ̄
  17. 17. ラムダ式 – ありそうな例  interfaceを導入する  interface PersonFilter { /** * pをフィルタに通過させる場合はtrueを返します。 */ boolean test(Person p); }
  18. 18. ラムダ式 – ありそうな例  メソッド呼び出し側でフィルタ条件のプログラムを 書く (匿名クラスを利用)  public void main(){ method(list, new PersonFilter(){ boolean test(Person p) { return p.age >= 20; } }); }  void method(List<Person> list, PersonFilter filter) { for(Person p : list) { if(filter.test(p)) { doSomething(p); } } }
  19. 19. ラムダ式 – ありそうな例  メソッド呼び出し側でフィルタ条件のプログラムを 書く (匿名クラスを利用)  public void main(){ method(list, new PersonFilter(){ boolean test(Person p) { return p.age >= 20; } }); }  void method(List<Person> list, PersonFilter filter) { for(Person p : list) { if(filter.test(p)) { doSomething(p); } } } 絞り込み条件を変更しても 処理する側は変更なし
  20. 20. ラムダ式 – ありそうな例  匿名クラスの記法は無駄が多い(定型文が多い)  method(list, new PersonFilter(){ boolean test(Person p) { return p.age >= 20; } });
  21. 21. ラムダ式 – ありそうな例  匿名クラスの記法は無駄が多い(定型文が多い)  method(list, new PersonFilter(){ boolean test(Person p) { return p.age >= 20; } }); やりたいこと 定型文
  22. 22. ラムダ式
  23. 23. ラムダ式 – ありそうな例  ラムダ式を使った記法  method(list, p -> p.age >= 20);
  24. 24. ラムダ式 – ありそうな例  ラムダ式を使った記法  method(list, p -> p.age >= 20); アロー演算子 (ハイフン+大なり)
  25. 25. ラムダ式 – ありそうな例  ラムダ式を使った記法  method(list, p -> p.age >= 20); 引数 返す値
  26. 26. ラムダ式 – ありそうな例  ラムダ式 = 匿名クラスの省略記法  匿名クラス  new PersonFilter(){ boolean test(Person p) { return p.age >= 20; } });  ラムダ式  p -> p.age >= 20
  27. 27. ラムダ式 – ありそうな例  省略しない書き方  method(list,(Person p) -> { return p.age >= 20;}); 引数 処理
  28. 28. ラムダ式 – ありそうな例  省略しない書き方  method(list,(Person p) -> { return p.age >= 20;}); 引数の型が推測可能 な場合は不要
  29. 29. ラムダ式 – ありそうな例  省略しない書き方  method(list, (p) -> { return p.age >= 20;}); 引数1個なら カッコは不要
  30. 30. ラムダ式 – ありそうな例  省略しない書き方  method(list, p -> { return p.age >= 20;}); 単に値を返すだけなら 式だけを書けばOK
  31. 31. ラムダ式 – ありそうな例  省略しない書き方  method(list, p -> p.age >= 20);  ↑同じ!↓  method(list,(Person p) -> { return p.age >= 20;});
  32. 32. ラムダ式 – 記法の例  引数0個  () -> 1  引数1個  (x) -> x * 2  x -> x * 2  引数1個の場合のみ引数のカッコを省略できる  引数2個  (a, b) -> a - b
  33. 33. 他の例
  34. 34. ラムダ式 – 他の例  Android とか (イベントドリブンでよく見かけるパター ン)  Buttonがクリックされたときの処理を設定する  匿名クラス  button.addOnClickListener(new OnClickListener(){ void onClick() { doSomething(); } });  ラムダ式  button.addOnClickListener( () -> { doSomething(); });
  35. 35. ラムダ式 – 他の例  Android とか (イベントドリブンでよく見かけるパター ン)  Buttonがクリックされたときの処理を設定する  匿名クラス  button.addOnClickListener(new OnClickListener(){ void onClick() { doSomething(); } });  ラムダ式  button.addOnClickListener( () -> { doSomething(); }); ・行数が少ない ・インデントが浅い
  36. 36. 関数型interface
  37. 37. どんなinterfaceにもラムダ式を渡せるの?  引数の型が「関数型interface」の条件を満たしてい る場合だけ  ≒ メソッド数が1個のinterfaceのこと  例外: デフォルトメソッドはあってもいい etc...  interface Example { // メソッド1個なので関数型interface void hoge (); }
  38. 38. @FunctionalInterface アノテーション  interfaceが関数型interfaceであると宣言するアノテー ション  これを付けると「関数型interface」の条件を満たさない ときにコンパイルエラーにしてくれる  付けなくても条件を満たせば関数型interfaceになる  @FunctionalInterface interface InvalidExample { // メソッド2個なので関数型interfaceではない // コンパイルエラー void methodA(); void methodB(); }
  39. 39. 標準の関数型interface
  40. 40. ラムダ式 – 標準の関数型interface  例ではこのようなinterfaceを自分で定義した  interface PersonFilter { /** * pをフィルタに通過させる場合はtrueを返します。 */ boolean test(Person p); }  よく使うinterfaceが標準で定義されている  interface Predicate<T> { boolean test(T elem); // 実際にはもうちょっと複雑な定義 }
  41. 41. ラムダ式 – 標準の関数型interface  標準の関数型interfaceを使う場合  public void main(){ method(list, p -> p.age >= 20); }  void method(List<Person> list, Predicate<Person> filter) { for(Person p : list) { if(filter.test(p)) { doSomething(p); } } }
  42. 42. ラムダ式 – 標準の関数型interface  いろいろある  引数なし, 戻り値なし  Runnable  引数なし, 戻り値T  Supplier<T>  引数T, 戻り値なし  Consumer<T>  引数T, 戻り値U  Function<T, U>  引数T, 戻り値boolean  Predicate<T>  ほかに30種類くらいあります
  43. 43. メソッド参照  interfaceのメソッドと同じシグネチャを持つメソッ ドがあれば、メソッド自体を引数で渡せる  ラムダ式  button.addOnClickListener(() -> {doSomething();});  メソッド参照  button.addOnClickListener(this::doSomething);  コロン2個の後にメソッド名  ラムダ式よりもコードが短くなる  引数リストが隠れるのでわかりづらくなる場合がある
  44. 44. Stream API
  45. 45. Stream API の導入 – for文からの変換  5文字より長い文字列を大文字に変換して処理を行う  for(String s : list) { if (s.length() > 5) { String upper = s.toUpperCase(); method(upper); } }
  46. 46. Stream API の導入 – for文からの変換  5文字より長い文字列を大文字に変換して処理を行う  for(String s : list) { if (s.length() > 5) { String upper = s.toUpperCase(); method(upper); } } 絞り込み (filter)
  47. 47. Stream API の導入 – for文からの変換  5文字より長い文字列を大文字に変換して処理を行う  for(String s : list) { if (s.length() > 5) { String upper = s.toUpperCase(); method(upper); } } 変換 (map : 写像)
  48. 48. Stream API の導入 – for文からの変換  5文字より長い文字列を大文字に変換して処理を行う  for(String s : list) { if (s.length() > 5) { String upper = s.toUpperCase(); method(upper); } } 順次処理 (for each)
  49. 49. Stream API の導入 – for文からの変換  5文字より長い文字列を大文字に変換して処理を行う  for(String s : list) { filter (5文字より長い) map (大文字に変換) forEach (methodで処理) }
  50. 50. Stream API の導入  Stream APIによる記法  list.stream() .filter( s -> s.length() > 5) .map( s -> s.toUpperCase()) .forEach( s -> {method(s);} );
  51. 51. Stream API の導入  Stream APIによる記法  list.stream() .filter( s -> s.length() > 5) .map( s -> s.toUpperCase()) .forEach( s -> {method(s);} ); メソッドチェイン (4行で1文)
  52. 52. Stream API の導入  Stream APIによる記法  list.stream() .filter( s -> s.length() > 5) .map( s -> s.toUpperCase()) .forEach( s -> {method(s);} );  for(String s : list) { if (s.length() > 5) { String upper = s.toUpperCase(); method(upper); } } しっぽが無い
  53. 53. Stream API のメソッド
  54. 54. Stream API のメソッド - Streamの始め方  ListからStreamを作成する  List list = new ArrayList(Arrays.asList(“a”, “b”, “c”)); list.stream()  配列からStreamを作成する  String[] array = {“a”, “b”, “c”}; Arrays.stream(array)  整数を列挙したStreamを作成する  IntStream.range(0, 10)  for(int i=0; i<10; i++) と同じ  IntStream.rangeClosed(0, 10)  for(int i=0; i<=10; i++) と同じ  テキストファイルなどから  BufferedReader br = /*省略*/; br.lines()  1行ぶんの文字列を1要素としたStreamになる
  55. 55. Stream API のメソッド – Streamに対する処理  中間処理と終端処理がある  中間処理  Streamの要素を変化させる  戻り値はStream  メソッドチェインで処理が継続  終端処理  Streamの要素を使って 最終的な結果を得る or 処理を行う  戻り値は void とか 要素の型 とか boolean とか
  56. 56. Stream API のメソッド – 中間処理  filter (Predicate<T>)  Streamの要素を絞り込む  map (Function<T, U>)  Streamの要素を変換する  別の型に変えてもok  .map(p -> p.name) とか(Person → String)  skip (long n)  Streamの最初のn個の要素を飛ばす  peek (Consumer<T>)  各要素を処理する。forEachに似ているが、Streamを継続できる点で異 なる  デバッグ用  list.stream().peek( s -> {log.debug(s);}).…  etc.
  57. 57. Stream API のメソッド – 終端処理  forEach (Consumer<T>)  各要素を処理する  拡張for文とほぼ同じ使い方  for( String s : list) { }  list.stream().forEach( s -> { });  anyMatch (Predicate<T>) allMatch(Predicate<T>)  条件に一致する要素が存在するか / 全て一致するか を booleanで返す  collect (Collector)  Streamの全要素を格納したコレクションを生成して返す  引数には Collectors.toList() などを渡せる  etc.
  58. 58. 色々な例
  59. 59. Stream API – 他の例  Listの中身が全て条件を満たすかどうか  Java 7  boolean valid = true; for(Person p : list) { if( p.age < 18 ){ valid = false; break; } }  Java 8  boolean valid = list.stream() .allMatch( p -> p.age >= 18 );
  60. 60. Stream API – 他の例  Listの要素を標準出力に表示  java 7  for(String s : list) { System.out.plintln(s); }  java 8 (ラムダ式)  list.stream().forEach(s -> {System.out.println(s);});  java 8 (メソッド参照)  list.stream().forEach(System.out::println);
  61. 61. Stream API – 他の例  Listの要素を絞り込んで新しいListに格納する  Java 7  List<String> newList = new ArrayList<>(); for (String s : list) { if (s.length > 5){ newList.add(s); } }  Java 8  List<String> newList = list.stream() .filter( s -> s.length() > 5 ) .collect(Collectors.toList());
  62. 62. Stream API – 他の例  Listの要素を全て変換する  List#replaceAll  (Stream APIではなくListの新メソッド)  Java 7  List<String> newList = new ArrayList<>(); for(String s : list) { newList.add(s.toUpperCase()); }  Java 8  list.replaceAll( s -> s.toUpperCase() );
  63. 63. Stream API – 他の例  Mapの要素を順次処理  Map#forEach  (Stream API ではなくMapの新メソッド)  java 7  for(String k : map.keySet()){ Object v = map.get(v); method(k, v); }  java 8  map.forEach( (k, v) -> { method(k, v); } );
  64. 64. まとめ
  65. 65. まとめ  ラムダ式  匿名クラスの省略記法  関数型interfaceを引数にとるメソッドに渡せる  標準の関数型interfaceをうまく利用したい  Stream API  コレクションに新しく用意された便利な操作方法  Stream生成 → 中間処理*n → 終端処理  for文やwhile文はだいたいStream APIに書き換えできる  for文禁止時代の到来
  66. 66. ご清聴ありがとう ございました
  67. 67. 質問&雑談タイム

×