Love PG , Liquor & Music

プログラマー備忘録やお酒や音楽

Java8のラムダ式ってイラネ(゚⊿゚)

ここ数か月Javaから離れた生活を送ってきたのですが、久しぶりにJavaを入れたらVer8になっていたので少し習得する意味を込めて触れてみようと思い立ちました。 公式も謳っていますが、今回のバージョンアップで一番の目玉は何といってもラムダ式が書けるようになったことらしいです。

Java8のラムダ式って?

凄く簡単にいうとコード量をだいぶ削減できる書き方です。 関数を疑似的にオブジェクトとして扱うようなイメージなのかなー程度に思ってます。 C言語とかで使ってる関数ポインタに相当するようなものがJavaにはなかったのですが、これが実装されたような感じです。

どういうコードが削減できるの?

結構限られていて、第一級関数で関数型インターフェースで表現できるものだけです。 つまり結構おなじみのRunnableインターフェースのrunメソッドとかみたいな実装できるメソッドが1個だけのInterfaceです。 記載サンプルは死ぬほどネットに転がってるので割愛します。

なんでわざわざややこしくなるような記法を追加したの?

正直、削減できたコード量は簡単な処理だと2-3行、ちょっと複雑になっても数十行程度です。 大規模なシステムで書いたとしても0.5k行くか行かないかくらいでしょう。 で、大規模なシステムならいろいろなエンジニア、デベロッパーがいます。 それだったら、たかだか500行削除するよりは、Java7標準のわかりやすく・見やすく・共有しやすい従来のコードで書いたほうがまだましです。

コード削減が結構注目されているラムダ式記法ですが、オラクル公式見解では並列処理を簡単に実装できるというところにあります。 つまり、同時に提供されたStreamと組み合わせることで初めてJavaでラムダを使うメリットが出てくるってことです。 ただ単に、嫌がらせレベルで可読性を下げたり不慣れな記法でバグを大量発生させようとかいうオラクルの目論見ではないってことらしいです。

ラムダの使いどころ その1

上記で述べましたが、並列処理を行わせたいときに使うのが一番でしょう。メソッド一本噛ませるだけでできちゃいます。 特にコレクションを扱う上では凄くイケてる感じの記法になります。もうfor分を腐るほど書かなくてもいいんです!

例:並列処理を使って電気タイプで高さが50以上のポケモンを体重順に並び替えて取得する

List<String> box = pokemons.stream().parallel()
  .filter(p -> p.getType().equals("電気"))
  .filter(p -> p.getHeight() > 50)
  .sorted(Comparator.comparingInt(Pokemon::getWeight))
  .map(Pokemn::getName)
  .collect(Collectors.toList());

1行ののparallel()つけるだけで勝手に並列処理してくれます。 Streamと組み合わせることによって、見た目も結構すっきりかけます。 もちろん、同一JVM上での並列処理の話なので分散コンピューティング行いたいときはRMIとか組み合わせると便利かもです。

ラムダの使いどころ その2

非同期処理を実現するときに、関数ポインタとしてフレームワーク的な何かへのコールバックを実現するとかできそうかも。

最後に

特に並列処理で今まで困ったことはないし、変な書き方がただ追加されたただの改悪だと個人的に思ってます。 そもそもコレクションを扱う上で並列処理が必要って状況が思い浮かばないし、そういう状況に置かれるってことはまずストレージやDBからのデータ取得方法を再検討したほうが効率がいいと思います。

実はこのヴァージョンアップは、Javaを本格的に関数型プログラミングへ向かわせる布石とも言われてますがほんとのところはどうなのでしょうか・・・