2014の17日目になります。昨日16日は@zephiransasさんの「Lambda-behaveでテストを書こう」でした。Java8の素晴らしき世界Java8を使ってプログラミングしていると、新しい機能を色々と使うことで簡潔で読みやすいコードを記述することが出来ます。これが思いの外楽しくるんるん気分でコードを書くことが出来ます。今までのように型をいちいち書かなきゃとかネスト地獄みたいなところを、少しだけ、でも大胆に改善することが出来、久々にJavaでコードを書いていて楽しいと思った時間でした。JavaでJava8を利用した開発をしていたのですが、その中でStreamとOptionalを使ってコードを記述するのが、個人的にとても気に入ったので、このエントリーではStreamの機能の一端をこんな風に使っていました、という紹介とラムダ式の省略記法の変更の仕方を紹介したいと思います。StreamとはJava8では、Streamパッケージが追加されています。sumなどなど)を実現することが出来るようです。Javaなどを使えば今までも使えましたけど)。ラムダ式前提の機能なので見た目見慣れない点も多くありますが、慣れるとネストが深くなりがちな処理もスッキリと見通しが良いコードになります。sortedなどを使いはじめると、無闇やたらとfor文を憎むようになり、for文を出来るだけ駆逐したくなる病気にかかるようです。いう私も病気に羅漢しました。for文を見ると、こうお腹の底からムズムズする何かが這い上がってくる感じがします。そんな素晴らしきStreamの機能の一部をコードと共にご紹介しますStreamを使うとこんなに楽まずは余計な情報の記述を行う必要がないので、必然的にコードのタイプ量は削減されます。複雑な条件の処理を行う際に、非常にコードが理解しやすい構造になります。通常条件といえば、ifやらswitchを使って条件分岐を行うかと思いますが、気をつけてないと後から条件をたそうとした時に、カオスな状態になって白目を剥くことになります。いった状態を改善することが出来ます。サンプルコードこんなクラスを定義してみます。PersonDtoのファクトリメソッドにはPersonクラスのインスタンスを受け取って適当に処理してPersonDtoクラスのインスタンスを返すようなものを定義します。}}[/java]<h3>Streamを使わずに変換してみる</h3><p>旧来の書き方だとPersonのListからPersonDtoへのリストの変換はこんな感じでしょうか。}}いずれも実行結果は以下のようになります。OTHERStreamを使った方を見ると、ちょっとだけ削減された気がします。「あとなんか意味の分からん記述入ってね?」ちょっと待って。ここで判断するのは早急です。僕のサンプルコードもアレですが、以下の理由を読んでからでも遅くはないですよ!記述する量これはすでにわかっている余計な情報を大きく削減してます。ラムダ式の引数は型推論によって型が自動的に決まるので、型をいちいち書く必要がありません。IDEのサポートがあるとは言え、やはりすでにわかっている型を明示的に書くよりも書かない方が格段に早いし無駄がないのではないでしょうか。このpersonは勝手にPersonクラスに推論されてるので型を指定する必要なしこの例を見ると、streamをmapしてからcollectしています。それぞれ、型は次のように遷移しています。List<PersonDto>このように次々と形を変えています。明示的に型を記述する必要はありません。各処理の返却値の型から自動的に型を判別してくれるので、こういった宣言が不要になっています。見覚えのない記述.map(PersonDto::create)、これが初見で出てくると訳が分からんのですが、省略した記法になっているだけなので基本的なラムダ式から段階的に変化させていくことができます。こちらを一度理解しておくと分かりやすいです。ラムダ式の記述をちょっとずつ変化させていきます。これが基本的な形です。})複数の処理を行わないのであれば1ラインでreturnが不要になります。.map(PersonDto::create)ラムダ式の引数をそのまま何もせずにメソッドの入力する場合は、このようなメソッド参照の記法が使えるみたいです。Swiftのクロージャの簡易記法もそうですが、慣れるまでは一見さんお断り的な雰囲気を醸し出しています。IDEAを利用しているとこの辺りはIDEが色々と注意してくれるので、指示通りにするだけで第2段階まではすぐ出来ます。見慣れると第1,2段階を飛ばして3段階目までパッと変換できます(多分)処理の途中に変換やフィルタ処理をInjectionするのが簡単Streamで実装していて一番感じたのは、今成立しているプログラムの構造を壊さずに条件や処理をInjectionすることができるということでした。これに成人のみのデータのみ変換して欲しい場合は以下のように記述します。.collect(Collectors.toList());プログラムの前後関係には一切手を入れず、filterを通過した時点ですでに対象データの抽出は完了しているので、あとは先ほどと同じように変換してあげるだけです。非常に分かりやすい構造です。その処理が通過した時点で結果が出ているものなので、for文と違い最後まで実行しないとどのような状態になっているかがわかりづらいということがありません。集計した結果を自由に変えることが出来るfilterやmapなどを通じて色々と処理した結果ですが、これもまた様々な形に自在に変えることができます。試しに年齢をKeyにしたMapにしてみましょう。for文でも書けなくはないですが、変更となると結構面倒な記述をする必要がありそうです。dto.name.length()));これも途中までの処理には一切手をつけていません。最後のcollectのみ変更を加えています。これだけで結果をListから任意のKeyを持ったMapへ変更できます。重複したKeyがある場合はListとしてまとめてくれます。ちなみに結果は以下のようになります。gender:OTHER}]}試しに旧来のコードで書いてみましょう。list);}少し過剰な感じがしますが、こんな感じじゃないでしょうか。この辺りはStreamを使った記述の方が圧倒的に分かりやすいですね。各要素が条件を満たすか検証したいこれは値のValidationの時とかに使ったりするのではないでしょうか。Listの中のデータをチェックして全てValidからInvalidなデータを含むかの試験を考えた時、旧来の方法だとfor文のその側にbooleanの値を定義して、条件をPassしたかどうかによってそれを書き換え、返すという方法でしょうか。match;うーん、何となくバグを埋め込みそうな気配がします。falsel;と書くやり方でしょうか。いずれにしてもあまり綺麗な書き方には見えません。Streamで書きなおしてみます。falseallMatchは、各要素が全て条件式に対してtrueでなければtrueを返しません。それ以外はfalseです。どれか一つでもtrueならばPassするのは、anyMatchです。trueこれは明らかにStreamを利用したコードの方が綺麗で分かりやすく、記述量も少ないですね。まとめ今回は当初flatMapなどを使ったサンプルもたくさんモリモリで出して行きたかったのですが、他には出てなさそうな良さげなサンプルコードが思いつかなかったため、大変中途半端な感じでぐぬぬ感があります。案件でOptionalと共に使いまくっていて色々思いつくかなと思っていたのですが、いざサンプルコードを考えるとなると非常に難しかったです。Streamを利用した処理の良い所は、中間処理の途中でも、何の処理を行って今現在どういうデータになっているかが一目瞭然で分かることではないでしょうか。for文の場合は、全体を最後まで見渡さないと、どのような結果になっているかがなかなか予測しづらいものです。この辺りをうまく使うと、より不具合の少ない簡潔で分かりやすいコードが記述できると思います。Java8はラムダ式を初め、StreamやOptionalなど今後のコードの書き方や考え方がガラッと変わるような機能が満載です。Streamにしてもまだまだたくさんの機能があり、まだまだほんの一部しか触れていません。今回Java8の機能の一つを少し紹介してみて、これをきっかけに最新のJavaに興味を持ってくれる人がいれば幸いです。1,520,267札幌へ出向中。興味の向く方向が爆発四散。リモート】クラスメソッドの会社説明会を開催しますクラスメソッドでは、AWS・AI・ビッグデータ・モバイルなどの技術職や営業のメンバーとして一緒にお仕事をする仲間を大募集しています。#cmdevio新型コロナウイルスの感染拡大を受け、本イベントを延期させていただくことになりました(開催時期未定)。お申し込みいただいた皆様には大変申し訳ございませんが、何卒ご理解いただけますようよろしくお願いいたします。AWSについてライトに色んな情報交換をしましょう。カフェ店長のオカノです。今日はオフィスに用があるので、通勤ラッシュを避けて出社しました。この子は新メンバーのさめくんです。在宅勤務が推奨されているのでオフィスが閑散としており、すこしさみしそうです。使いたいときの注意点を書きました。本が出ていたので読んでみたところよかったので紹介させていただきます。