Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
SlideShare a Scribd company logo
Java 8 勉強会
怖くない!ラムダ式, Stream API
2015/09/30 株式会社デーコム Ken
自己紹介
 名前
 Ken
 所属
 株式会社デーコム (4年目)
 やってること
 Webアプリの実装
 Java, SAStruts
 Javascript, CSS3
 jQuery, flotr2(グラフ表示)
 SPARQL (sqlっぽいやつ)
 今熱いこと
 数学, 哲学
 『数学ガール』(結城浩) とか
 コンピュータ将棋(電王戦)
自己紹介 – つづき
 趣味とか
 趣味プログラミング(まれに)
 なぞぷよ, 2chブラウザ, ルービックキューブ用タイマーなど
 音ゲー
 beatmaniaIIDX 全曲ハードクリア(未解禁曲以外)
 Dance Dance Revolution 足鳳凰
 Splatoon
 ウデマエ S, 最近のブキ:ノヴァブラスターネオ
 タイムアタック
 ルービックキューブ (自己べ22秒, 最近は40秒)
 海腹川背, 星のカービィSDX, ロックマンX4
勉強会のtarget
 Java 6,7の知識で止まっている方
 ラムダ式、あぁあの 気持ち悪い やつね という方
 StreamAPI、って何だ という方
Java 8の新機能のうち、今回話さないこと
 話さないこと
 Stream API の parallel()
 (使ったことない & 排他など複雑なので)
 Optional
 (準備できませんでした)
 DateTime API
 デフォルトメソッド
 など...
前提知識
 Java 6
 interface
 匿名クラス
 ジェネリクス
ラムダ式 (Lambda Expression)
舎 λ λ λ λ.....
x -> x * 2
ラムダ式
 x -> x * 2
 x を引数に取って、x * 2 を返す
 メソッドとして考えると
 int convert(int x) {
return x * 2;
}
 JavaScriptなら
 function(x){
return x * 2;
}
ありそうな例
ラムダ式 - ありそうな例
 人を表すクラス
 class Person {
String name;
int age;
}
ラムダ式 - ありそうな例
 20歳以上の人だけ処理する
 public void main(){
method(list, 20);
}
 void method (List<Person> list, int minAge) {
for(Person p : list) {
if(p.age >= minAge)
doSomething(p);
}
}
ラムダ式 - ありそうな例
 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);
}
}
ラムダ式 - ありそうな例
 名前が「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);
}
}
ラムダ式 - ありそうな例
 名前が「B」で終わる人だけを処理
 年齢が偶数の人だけを処理
 名前の文字数が10以上の人だけを処理
・
・
・
_人人人人人人_
> 引数地獄 <
 ̄Y^Y^Y^Y^Y ̄
ラムダ式 – ありそうな例
 interfaceを導入する
 interface PersonFilter {
/**
* pをフィルタに通過させる場合はtrueを返します。
*/
boolean test(Person p);
}
ラムダ式 – ありそうな例
 メソッド呼び出し側でフィルタ条件のプログラムを
書く (匿名クラスを利用)
 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);
}
}
}
ラムダ式 – ありそうな例
 メソッド呼び出し側でフィルタ条件のプログラムを
書く (匿名クラスを利用)
 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);
}
}
}
絞り込み条件を変更しても
処理する側は変更なし
ラムダ式 – ありそうな例
 匿名クラスの記法は無駄が多い(定型文が多い)
 method(list, new PersonFilter(){
boolean test(Person p) {
return p.age >= 20;
}
});
ラムダ式 – ありそうな例
 匿名クラスの記法は無駄が多い(定型文が多い)
 method(list, new PersonFilter(){
boolean test(Person p) {
return p.age >= 20;
}
});
やりたいこと
定型文
ラムダ式
ラムダ式 – ありそうな例
 ラムダ式を使った記法
 method(list, p -> p.age >= 20);
ラムダ式 – ありそうな例
 ラムダ式を使った記法
 method(list, p -> p.age >= 20);
アロー演算子
(ハイフン+大なり)
ラムダ式 – ありそうな例
 ラムダ式を使った記法
 method(list, p -> p.age >= 20);
引数 返す値
ラムダ式 – ありそうな例
 ラムダ式 = 匿名クラスの省略記法
 匿名クラス
 new PersonFilter(){
boolean test(Person p) {
return p.age >= 20;
}
});
 ラムダ式
 p -> p.age >= 20
ラムダ式 – ありそうな例
 省略しない書き方
 method(list,(Person p) -> { return p.age >= 20;});
引数 処理
ラムダ式 – ありそうな例
 省略しない書き方
 method(list,(Person p) -> { return p.age >= 20;});
引数の型が推測可能
な場合は不要
ラムダ式 – ありそうな例
 省略しない書き方
 method(list, (p) -> { return p.age >= 20;});
引数1個なら
カッコは不要
ラムダ式 – ありそうな例
 省略しない書き方
 method(list, p -> { return p.age >= 20;});
単に値を返すだけなら
式だけを書けばOK
ラムダ式 – ありそうな例
 省略しない書き方
 method(list, p -> p.age >= 20);
 ↑同じ!↓
 method(list,(Person p) -> { return p.age >= 20;});
ラムダ式 – 記法の例
 引数0個
 () -> 1
 引数1個
 (x) -> x * 2
 x -> x * 2
 引数1個の場合のみ引数のカッコを省略できる
 引数2個
 (a, b) -> a - b
他の例
ラムダ式 – 他の例
 Android とか (イベントドリブンでよく見かけるパター
ン)
 Buttonがクリックされたときの処理を設定する
 匿名クラス
 button.addOnClickListener(new OnClickListener(){
void onClick() {
doSomething();
}
});
 ラムダ式
 button.addOnClickListener( () -> {
doSomething();
});
ラムダ式 – 他の例
 Android とか (イベントドリブンでよく見かけるパター
ン)
 Buttonがクリックされたときの処理を設定する
 匿名クラス
 button.addOnClickListener(new OnClickListener(){
void onClick() {
doSomething();
}
});
 ラムダ式
 button.addOnClickListener( () -> {
doSomething();
});
・行数が少ない
・インデントが浅い
関数型interface
どんなinterfaceにもラムダ式を渡せるの?
 引数の型が「関数型interface」の条件を満たしてい
る場合だけ
 ≒ メソッド数が1個のinterfaceのこと
 例外: デフォルトメソッドはあってもいい etc...
 interface Example {
// メソッド1個なので関数型interface
void hoge ();
}
@FunctionalInterface アノテーション
 interfaceが関数型interfaceであると宣言するアノテー
ション
 これを付けると「関数型interface」の条件を満たさない
ときにコンパイルエラーにしてくれる
 付けなくても条件を満たせば関数型interfaceになる
 @FunctionalInterface
interface InvalidExample {
// メソッド2個なので関数型interfaceではない
// コンパイルエラー
void methodA();
void methodB();
}
標準の関数型interface
ラムダ式 – 標準の関数型interface
 例ではこのようなinterfaceを自分で定義した
 interface PersonFilter {
/**
* pをフィルタに通過させる場合はtrueを返します。
*/
boolean test(Person p);
}
 よく使うinterfaceが標準で定義されている
 interface Predicate<T> {
boolean test(T elem);
// 実際にはもうちょっと複雑な定義
}
ラムダ式 – 標準の関数型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);
}
}
}
ラムダ式 – 標準の関数型interface
 いろいろある
 引数なし, 戻り値なし
 Runnable
 引数なし, 戻り値T
 Supplier<T>
 引数T, 戻り値なし
 Consumer<T>
 引数T, 戻り値U
 Function<T, U>
 引数T, 戻り値boolean
 Predicate<T>
 ほかに30種類くらいあります
メソッド参照
 interfaceのメソッドと同じシグネチャを持つメソッ
ドがあれば、メソッド自体を引数で渡せる
 ラムダ式
 button.addOnClickListener(() -> {doSomething();});
 メソッド参照
 button.addOnClickListener(this::doSomething);
 コロン2個の後にメソッド名
 ラムダ式よりもコードが短くなる
 引数リストが隠れるのでわかりづらくなる場合がある
Stream API
Stream API の導入 – for文からの変換
 5文字より長い文字列を大文字に変換して処理を行う
 for(String s : list) {
if (s.length() > 5) {
String upper = s.toUpperCase();
method(upper);
}
}
Stream API の導入 – for文からの変換
 5文字より長い文字列を大文字に変換して処理を行う
 for(String s : list) {
if (s.length() > 5) {
String upper = s.toUpperCase();
method(upper);
}
}
絞り込み
(filter)
Stream API の導入 – for文からの変換
 5文字より長い文字列を大文字に変換して処理を行う
 for(String s : list) {
if (s.length() > 5) {
String upper = s.toUpperCase();
method(upper);
}
}
変換
(map : 写像)
Stream API の導入 – for文からの変換
 5文字より長い文字列を大文字に変換して処理を行う
 for(String s : list) {
if (s.length() > 5) {
String upper = s.toUpperCase();
method(upper);
}
}
順次処理
(for each)
Stream API の導入 – for文からの変換
 5文字より長い文字列を大文字に変換して処理を行う
 for(String s : list) {
filter (5文字より長い)
map (大文字に変換)
forEach (methodで処理)
}
Stream API の導入
 Stream APIによる記法
 list.stream()
.filter( s -> s.length() > 5)
.map( s -> s.toUpperCase())
.forEach( s -> {method(s);} );
Stream API の導入
 Stream APIによる記法
 list.stream()
.filter( s -> s.length() > 5)
.map( s -> s.toUpperCase())
.forEach( s -> {method(s);} );
メソッドチェイン
(4行で1文)
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);
}
}
しっぽが無い
Stream API のメソッド
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になる
Stream API のメソッド – Streamに対する処理
 中間処理と終端処理がある
 中間処理
 Streamの要素を変化させる
 戻り値はStream
 メソッドチェインで処理が継続
 終端処理
 Streamの要素を使って
最終的な結果を得る or 処理を行う
 戻り値は void とか 要素の型 とか boolean とか
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.
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.
色々な例
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 );
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);
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());
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() );
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); } );
まとめ
まとめ
 ラムダ式
 匿名クラスの省略記法
 関数型interfaceを引数にとるメソッドに渡せる
 標準の関数型interfaceをうまく利用したい
 Stream API
 コレクションに新しく用意された便利な操作方法
 Stream生成 → 中間処理*n → 終端処理
 for文やwhile文はだいたいStream APIに書き換えできる
 for文禁止時代の到来
ご清聴ありがとう
ございました
質問&雑談タイム

More Related Content

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

  • 1. Java 8 勉強会 怖くない!ラムダ式, Stream API 2015/09/30 株式会社デーコム Ken
  • 2. 自己紹介  名前  Ken  所属  株式会社デーコム (4年目)  やってること  Webアプリの実装  Java, SAStruts  Javascript, CSS3  jQuery, flotr2(グラフ表示)  SPARQL (sqlっぽいやつ)  今熱いこと  数学, 哲学  『数学ガール』(結城浩) とか  コンピュータ将棋(電王戦)
  • 3. 自己紹介 – つづき  趣味とか  趣味プログラミング(まれに)  なぞぷよ, 2chブラウザ, ルービックキューブ用タイマーなど  音ゲー  beatmaniaIIDX 全曲ハードクリア(未解禁曲以外)  Dance Dance Revolution 足鳳凰  Splatoon  ウデマエ S, 最近のブキ:ノヴァブラスターネオ  タイムアタック  ルービックキューブ (自己べ22秒, 最近は40秒)  海腹川背, 星のカービィSDX, ロックマンX4
  • 4. 勉強会のtarget  Java 6,7の知識で止まっている方  ラムダ式、あぁあの 気持ち悪い やつね という方  StreamAPI、って何だ という方
  • 5. Java 8の新機能のうち、今回話さないこと  話さないこと  Stream API の parallel()  (使ったことない & 排他など複雑なので)  Optional  (準備できませんでした)  DateTime API  デフォルトメソッド  など...
  • 6. 前提知識  Java 6  interface  匿名クラス  ジェネリクス
  • 8. x -> x * 2
  • 9. ラムダ式  x -> x * 2  x を引数に取って、x * 2 を返す  メソッドとして考えると  int convert(int x) { return x * 2; }  JavaScriptなら  function(x){ return x * 2; }
  • 11. ラムダ式 - ありそうな例  人を表すクラス  class Person { String name; int age; }
  • 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. ラムダ式 - ありそうな例  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. ラムダ式 - ありそうな例  名前が「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. ラムダ式 - ありそうな例  名前が「B」で終わる人だけを処理  年齢が偶数の人だけを処理  名前の文字数が10以上の人だけを処理 ・ ・ ・
  • 17. ラムダ式 – ありそうな例  interfaceを導入する  interface PersonFilter { /** * pをフィルタに通過させる場合はtrueを返します。 */ boolean test(Person p); }
  • 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. ラムダ式 – ありそうな例  メソッド呼び出し側でフィルタ条件のプログラムを 書く (匿名クラスを利用)  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. ラムダ式 – ありそうな例  匿名クラスの記法は無駄が多い(定型文が多い)  method(list, new PersonFilter(){ boolean test(Person p) { return p.age >= 20; } });
  • 21. ラムダ式 – ありそうな例  匿名クラスの記法は無駄が多い(定型文が多い)  method(list, new PersonFilter(){ boolean test(Person p) { return p.age >= 20; } }); やりたいこと 定型文
  • 23. ラムダ式 – ありそうな例  ラムダ式を使った記法  method(list, p -> p.age >= 20);
  • 24. ラムダ式 – ありそうな例  ラムダ式を使った記法  method(list, p -> p.age >= 20); アロー演算子 (ハイフン+大なり)
  • 25. ラムダ式 – ありそうな例  ラムダ式を使った記法  method(list, p -> p.age >= 20); 引数 返す値
  • 26. ラムダ式 – ありそうな例  ラムダ式 = 匿名クラスの省略記法  匿名クラス  new PersonFilter(){ boolean test(Person p) { return p.age >= 20; } });  ラムダ式  p -> p.age >= 20
  • 27. ラムダ式 – ありそうな例  省略しない書き方  method(list,(Person p) -> { return p.age >= 20;}); 引数 処理
  • 28. ラムダ式 – ありそうな例  省略しない書き方  method(list,(Person p) -> { return p.age >= 20;}); 引数の型が推測可能 な場合は不要
  • 29. ラムダ式 – ありそうな例  省略しない書き方  method(list, (p) -> { return p.age >= 20;}); 引数1個なら カッコは不要
  • 30. ラムダ式 – ありそうな例  省略しない書き方  method(list, p -> { return p.age >= 20;}); 単に値を返すだけなら 式だけを書けばOK
  • 31. ラムダ式 – ありそうな例  省略しない書き方  method(list, p -> p.age >= 20);  ↑同じ!↓  method(list,(Person p) -> { return p.age >= 20;});
  • 32. ラムダ式 – 記法の例  引数0個  () -> 1  引数1個  (x) -> x * 2  x -> x * 2  引数1個の場合のみ引数のカッコを省略できる  引数2個  (a, b) -> a - b
  • 34. ラムダ式 – 他の例  Android とか (イベントドリブンでよく見かけるパター ン)  Buttonがクリックされたときの処理を設定する  匿名クラス  button.addOnClickListener(new OnClickListener(){ void onClick() { doSomething(); } });  ラムダ式  button.addOnClickListener( () -> { doSomething(); });
  • 35. ラムダ式 – 他の例  Android とか (イベントドリブンでよく見かけるパター ン)  Buttonがクリックされたときの処理を設定する  匿名クラス  button.addOnClickListener(new OnClickListener(){ void onClick() { doSomething(); } });  ラムダ式  button.addOnClickListener( () -> { doSomething(); }); ・行数が少ない ・インデントが浅い
  • 37. どんなinterfaceにもラムダ式を渡せるの?  引数の型が「関数型interface」の条件を満たしてい る場合だけ  ≒ メソッド数が1個のinterfaceのこと  例外: デフォルトメソッドはあってもいい etc...  interface Example { // メソッド1個なので関数型interface void hoge (); }
  • 38. @FunctionalInterface アノテーション  interfaceが関数型interfaceであると宣言するアノテー ション  これを付けると「関数型interface」の条件を満たさない ときにコンパイルエラーにしてくれる  付けなくても条件を満たせば関数型interfaceになる  @FunctionalInterface interface InvalidExample { // メソッド2個なので関数型interfaceではない // コンパイルエラー void methodA(); void methodB(); }
  • 40. ラムダ式 – 標準の関数型interface  例ではこのようなinterfaceを自分で定義した  interface PersonFilter { /** * pをフィルタに通過させる場合はtrueを返します。 */ boolean test(Person p); }  よく使うinterfaceが標準で定義されている  interface Predicate<T> { boolean test(T elem); // 実際にはもうちょっと複雑な定義 }
  • 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. ラムダ式 – 標準の関数型interface  いろいろある  引数なし, 戻り値なし  Runnable  引数なし, 戻り値T  Supplier<T>  引数T, 戻り値なし  Consumer<T>  引数T, 戻り値U  Function<T, U>  引数T, 戻り値boolean  Predicate<T>  ほかに30種類くらいあります
  • 43. メソッド参照  interfaceのメソッドと同じシグネチャを持つメソッ ドがあれば、メソッド自体を引数で渡せる  ラムダ式  button.addOnClickListener(() -> {doSomething();});  メソッド参照  button.addOnClickListener(this::doSomething);  コロン2個の後にメソッド名  ラムダ式よりもコードが短くなる  引数リストが隠れるのでわかりづらくなる場合がある
  • 45. Stream API の導入 – for文からの変換  5文字より長い文字列を大文字に変換して処理を行う  for(String s : list) { if (s.length() > 5) { String upper = s.toUpperCase(); method(upper); } }
  • 46. Stream API の導入 – for文からの変換  5文字より長い文字列を大文字に変換して処理を行う  for(String s : list) { if (s.length() > 5) { String upper = s.toUpperCase(); method(upper); } } 絞り込み (filter)
  • 47. Stream API の導入 – for文からの変換  5文字より長い文字列を大文字に変換して処理を行う  for(String s : list) { if (s.length() > 5) { String upper = s.toUpperCase(); method(upper); } } 変換 (map : 写像)
  • 48. Stream API の導入 – for文からの変換  5文字より長い文字列を大文字に変換して処理を行う  for(String s : list) { if (s.length() > 5) { String upper = s.toUpperCase(); method(upper); } } 順次処理 (for each)
  • 49. Stream API の導入 – for文からの変換  5文字より長い文字列を大文字に変換して処理を行う  for(String s : list) { filter (5文字より長い) map (大文字に変換) forEach (methodで処理) }
  • 50. Stream API の導入  Stream APIによる記法  list.stream() .filter( s -> s.length() > 5) .map( s -> s.toUpperCase()) .forEach( s -> {method(s);} );
  • 51. Stream API の導入  Stream APIによる記法  list.stream() .filter( s -> s.length() > 5) .map( s -> s.toUpperCase()) .forEach( s -> {method(s);} ); メソッドチェイン (4行で1文)
  • 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); } } しっぽが無い
  • 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. Stream API のメソッド – Streamに対する処理  中間処理と終端処理がある  中間処理  Streamの要素を変化させる  戻り値はStream  メソッドチェインで処理が継続  終端処理  Streamの要素を使って 最終的な結果を得る or 処理を行う  戻り値は void とか 要素の型 とか boolean とか
  • 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. 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.
  • 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. 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. 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. 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. 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); } );
  • 65. まとめ  ラムダ式  匿名クラスの省略記法  関数型interfaceを引数にとるメソッドに渡せる  標準の関数型interfaceをうまく利用したい  Stream API  コレクションに新しく用意された便利な操作方法  Stream生成 → 中間処理*n → 終端処理  for文やwhile文はだいたいStream APIに書き換えできる  for文禁止時代の到来