Java 8の新機能をエレガントに使いたい
Java 8ではラムダ式、Stream、Optional、インタフェースのデフォルト実装などなど、大量の新機能が追加されました。新機能を知らないという方は以下が参考になるかと思います。
こうした情報を見て、少なくとも私はJavaの時代が来たんじゃないかという印象を持ちました。もちろん、私の大好きなC#や人気のScalaと比べてしまうと、言語仕様の強力さ、記述の美しさでは劣ります。しかし、少なくとも現状ではWindows以外で使うならC#よりJavaですし、Scalaは一部の人が盛り上がっているという印象で、言語仕様以外の部分ではJavaに分があると思うのです。言語仕様の差が以前より縮まった現在、総合的に見ればJavaは選択肢に入るどころか、最強と言ってもいいのではないでしょうか。
とはいえ、使わずにどうこう言っても仕方ないので、実際に新機能でコードを書いて試してみました。よい点を紹介している記事はたくさん見かけるので、ここではその辺はさらっと一言程度に留めて、StreamとOptionalについての気になった点を中心に述べることにします。
Stream
Stream APIによって、コレクション操作の充実度は他の言語に劣らない程度にまで強化されました。コレクションに直接メソッドが追加されているわけではないため、一度streamを取得してから操作しなければならないというのは若干面倒ではありますが、第一印象は悪くありません。
ただ、実際に書いてみるとプリミティブ型がGenericsからハブられている関係で、まぁ使いにくいわけです。そのためにIntStream
とかDoubleStream
とかが用意されているのですが、これらの型は参照型全般で使われるStream
とは互換性がないため、開発者が意識して適宜変換しながら使い分ける必要があります。
Stream
にInteger
やDouble
を入れてしまえばいいのでは、と思われるかもしれませんが、sum()
とaverage()
などによる集計の機能はStream
には用意されていないので、mapToInt()
やmapToDouble()
で一度型を変換してから集計するか、あるいは自分でreduce()
で書くかということになります。どうでもいい車輪の再発明は避けるべきと考えると、mapToInt()
なるダサいメソッドを呼び出すのが現実的でしょう。
集計のことを考えると、プリミティブ型は基本的に専用のstreamにするのがよいと思いますが、プリミティブ型のstreamのmap()
は同じ型のStreamしか返せません。他のプリミティブ型や参照型を返したい場合には、doubles().map()
、longs().map()
、mapToObj()
を利用します。
map()
には対応するmapToObj()
があるのに対して、flatMap()
に対応するflatMapToObj()
は存在しません。プリミティブ型のstreamでflatMap()
して参照型を返したい場合には、boxed()
を呼び出してボクシングした型のStream
を得てからflatMap()
を使う必要があります。
Optional
Javaではnullが入り込む予知があることを見落としがちになるため、nullに対する適切な処理を強制する効果を見込めるOptional
は非常に有用だと思います。強いて難点を言うなら、Optional
に値が入っているかどうかで分岐して処理を行う場合に、あまりカッコよく書けないのが気になるところです。
といっても、以下のように値が入っている場合にだけ何らかの処理を行う、というのは問題ありません。
しかし、値が入っていない場合にも何らかの処理を行いたいとなると、Optional
を使わない場合と比べて一手間増えてしまいます。isPresent()
とget()
が入ってしまうOptional
の使い方は避けたいところですね。
map()
メソッドとorElseGet()
メソッドで書けないこともないですが、nullを返しておいて捨てるというのはどう考えてもスマートではありません。nullを置き換えるためにOptionalを導入しているはずなのに、コード上にnullが現れるという皮肉さがあるのは面白いですが。今のところはisPresent()
とget()
を使うのが現実的でしょう。
おわりに
これまでと比べれば遥かによくなっていると思いますが、どことなく残念な感があるのは否めません。また、C#の匿名型に相当するものもTupleもないので、メソッドチェーンでカッコいいコードを書くのはなかなか難しい気がします。そもそも、業務で書くなら記述のエレガントさよりコードを見て誰でも理解できることのほうが重要ですから、エンタープライズ向けで強いJavaに求めるべき方向性ではないのかもしれません。ただ、少なくとも趣味のプログラミングにおいてのJava熱から目が覚めたのは確かです。