【東京】◆Java SE 8勉強会◆女子部もラムダ式に挑戦! - Java女子部 | Doorkeeper
に参加してきました!
遅刻してしまって、前半の『Java SE 8の基礎解説』には出れなかったんだけど、
後半の『ラムダ式ハンズオン』で前半の『Java SE 8の基礎解説』で勉強した内容を試してみよう!
っていう感じだったので十分楽しめました!
参加者のみなさんは、(会場で手を挙げてアンケートとってたけど、)GitHub使った事ない人がほとんどで、
GitHubに自分のリポジトリありますかって質問に2人しか手が挙がらない感じだった。
でも、GitHubからPJをもってくるところとか、PJをIDEで開くところとかを、
運営の人が丁寧に教えてあげてて、初心者歓迎の言葉にうそはなかったんだ!と思った!*1
1時間半のハンズオンってことだったので、内容は絞ってたけど、
それでも、難しそう!と思ってたラムダ式、Streamに親しみをもてたので、
すごくいい感じだった!!
さくらばさん!運営の方々、みなさまみなさま、ありがとうございました!
勉強資料はこちら
勉強したこと
※内容に誤りがあったら教えてください><
基本の構文
(引数) -> {
実際の処理
}
例)
- 引数が0個のとき
() -> {
実際の処理
}
- 引数が1個のとき
※引数の()を省略することが出来る
x -> {
実際の処理
}
- 引数が複数のとき
(x, y) -> {
実際の処理
}
- 実際の処理が一文のとき
※{}を書かないで済む!『->』の前で改行してもOK
(引数) -> 実際の処理
ラムダ式の例
※実際に教材として使ったコードです
まずは、ふつうのコード
Function<String, Integer> function = new Function<String, Integer>() { @Override public Integer apply(String x) { return Integer.valueOf(x); } };
Function<T,R>は実装する必要のあるメソッドがapply(T t)のみ。
Function<T,R>のRとTは↓こういう意味
- T - 関数の入力の型
- R - 関数の結果の型
つまり、
- new Function<String, Integer>() ⇒ functionの宣言を見ればわかる。不要。
- @Override ⇒ 本質とは関係ない。不要。
- public Integer ⇒ functionの宣言を見ればわかる。不要。
- apply ⇒ Functionで実装するメソッドは一つ。特定可能。不要。
- (String ⇒ functionの宣言を見ればわかる。不要。
本質の部分は『xという引数をメソッド内でどのように使うか。』のところ。
ラムダ式を使うことで、
Function<String, Integer> function = x -> Integer.valueOf(x);
こんな感じで不要な部分をすべて除いて書くことができる*2
Stream API
Stream APIのメソッドは、中間操作をするものと終端操作をするものがある
今回勉強したのは↓このメソッド
中間操作
- filter
- map
- flatMap
終端操作
- forEach
- collect
使い方
終端操作を先に書いてから、中間操作として切り出せるものを切り出していく
終端操作のforEachよりも中間操作のfilterを先に使うのは、
filterで要素を事前に絞り込むことで、forEachで繰り返し処理として使用する要素を少なくすることが出来て、
処理を効率化することができる!からです。
Streamの例
private void printList(List<String> texts) { for (String text: texts) { if (text.startsWith("a")) { System.out.println(text); } } }
まずは、textsをStreamにして、終端操作のforEachをつかう
private void printList(List<String> texts) { texts.stream() .forEach(text -> { if (text.startsWith("a")) { System.out.println(text); } }); }
ifの部分はfilterとして切り出すことができる!
private void printList(List<String> texts) { texts.stream() .filter(text -> text.startWith("a")) .forEach(text -> { System.out.println(text); }); }
Streamを使うことで処理がわかりやすくなる!やったね₍₍⁽⁽(ી(´・ᴗ・`)ʃ)₎₎⁾⁾
例えば
toList()メソッドで、streamをListに変換することができる
private List<String> copyList(List<String> src) { List<String> dest = new ArrayList<>(); for (String element: src) { dest.add(element); } return dest; }
forEachを使うと、こうなる
private List<String> copyList1(List<String> src) { List<String> dest = new ArrayList<>(); src.forEach(element -> { dest.add(element); }); return dest; }
ただし、この状態ではラムダ式のなかでdestっていうラムダ式の外で宣言した変数を使ってしまっている!
これだと、スレッドセーフにならない!
基本的に、匿名クラスやラムダ式を使うときは中に閉じた実装にするべき!
ここで、collectメソッドを使って、streamをListにしちゃって、そのままdestに代入しちゃう!
collect()メソッドにCollectors.toList()を渡す事で、streamをListに変換することができる!
private List<String> copyList2(List<String> src) { List<String> dest = src.stream() .collect(Collectors.toList()); return dest; }
これで、見た目にもわかりやすい実装が出来る!!*3
Java8たのしい!
ほかにも、短い時間だったけど、いろいろなこと教えてもらいました!!
- IntStream
- map()
- mapToObj()
- groupingBy()
- flatMap()
などなど。。。
Java8たのしい!
*1:初心者向けって書いてあるのに初心者向けじゃない!みたいなの、たまーにありますよね…。
*2:『Function<String, Integer> function = Integer::valueOf;』こういう風に書けるっていうのは、今回のハンズオンではやりませんでした。GitHub上の解答には記載されてる!例えばコレのtestLambda4メソッド
*3:今回は練習用ソースだったので、Listの値をコピーする、っていう処理を実装をしました!本来はArrays.copy()を使う!