エンターテイメント!!

遊戯王好きのJavaエンジニアのブログ。バーニングソウルを会得する特訓中。

念願のJava8の現場に入って使ったStreamAPI

念願のJava8環境

念願のJava8環境に入れた!
Java8はリリース前からStreamAPI、Lambdaに興味を持って調べていて、やっと使える現場に入れた。

現場の状況

残念ながら現場のソースはJava8の記法を見かけない。。。。
実を言うと前にいた現場で、そのころはまだJava6だった。
切り替わるまえに諸々の事情により、離脱したが。
戻ってきて、環境がゴッソリ変わっていてビビった。
知っている人も半分くらい生き残っていて、若干気恥ずかしい感じがした。

話を戻して、ソースの件。
残念ながら、新規のクラスでもJava6の記法がしか見ない。。。。
Java7の記法すらないという悲しい事態。。。。
自分なりに考えた結果、そもそもJava8を使える人がいないのが原因だと思う。
業務を達成ばかりに目が行ってしまい、コードを見ていないと感じた。
せっかくJava8が使える現場にいるのだから、積極的に使うべきだと思うんですよ。
使えないから、分からないから使わないだと、いつまで経っても成長が望めないと思う。
使いたくても使えない人は山程いる(ハズ)なので、できれば使って欲しいところ。
というわけで、使って欲しい意味も込めて、自分がどう覚えたかを書き連ねる。
勉強したけど、結局分からない人の手助けになればと思う。

Java8とそれ以前のコードの比較

まずは何をおいても違いを覚えることだね。
下記はString配列の中身を出力する簡単なプログラム。(ちゃんと動作確認したから大丈夫!)

Java7以前(Java5~Java7)

gista2887020929979e17cf13af58ee5cb10

配列にあるものをforeach文を使用してprintln()で出力しているだけ。
これは誰でも分かるはず。

Java8

gist2b32d9d8537a75fef6ca9a2070663dd4

結果

両方共結果は同じ

1
2
3
4
5

考え方

Streamの考え方は、自分は自動車工場のラインを思い浮かべると楽に覚えられました。
自分が、工業高校出身ということもあるかも。。。

一番の問題は対象のデータは何で、何をしているか分からないこと。
foreach文であれば操作対象は、ハッキリ見える。
ここで上げた例だと、valueが操作対象であることが分かる。
StreamAPIでは、それが見えなくなるので、わからないとなる。

そこで、何が流れているのかをイメージするのに工場のラインを思い浮かべる。

f:id:suzaku0914:20160416014000j:plain

トヨタ自動車プリウス生産ライン。
ベルトコンベアとかで車のベースとなるものが流れてきて、それに対してエンジンつけたりハンドルつけたりする。
これがStreamAPIに例えられる。
ながれてくるベースは、Streamで流れてくる要素、それに対してエンジンつけたりすることは処理になる。
例だと、流れてきているものは、見えないけどlistの要素が流れている。それに対してエンジンつけたりする処理が、forEachOrdered内のSystem.out::printlnに当たる。

伝わったかな?
自分は、人とかなり違う存在として認識されることが多いから、伝わったか不安。
違うということは、特異だとゆうこと。他人と違う自分かっけー!

基本的には、何が流れているかを認識すれば、あとは処理内容はスンナリ頭に入る。
流れているものがわからないと、処理だけ見てもサッパリ分からない事態になる。
最初にLambdaと組み合わされたStreamAPIを見た自分がそうだった。
何を操作しているか分かることが一番重要。

一番よく使うもの

一番よく使うStreamAPIのメソッドは、今のところforEachOrdered()
foreach文の置き換えがforEachOrdered()になるので、多用する。
次に、foreach()とanyMatch()かな?
foreach()は順序気にする必要がないものに対してparallel()と組み合わせて使う。
anyMatchは、今までやっていたfor文を回して存在チェックとかに使う。
意外と使う場面があることに驚いた。
あとは、filter()とかよく使う。
今まで途中の処理を抜けて次のループへ行く場合は、for文の中にif文書いてたけど、filterが出てきて記述がフラットになった。
なんというか、if文が出てくるとインデントが多くなるし、意味合いが処理から読み解く必要があることが辛いんだよね。。。
その点、filter()はフラットに書けるし、何をしたいか分かりやすいのがいいと思った。

2016/04/23 追記
collectが結構便利なのに気づいた。
最終的に欲しいものがリストの場合は、mapで変換した要素をcollect(Collectors.toList())使って変換したリスト取得することが多い 実際に使ってみて、使いやすさを実感した。
collect使うと、foreach()/forEachOredered()は、ほぼ使わない。

forを使わざるを得ないパターン

特定位置のものに対して処理する場合。
ほとんどないから使うパターンはほぼないんですけどね!

Lambdaの必要性

StreamAPIの話ばかりしたけど、Lambdaは結構重要だと思う。
Lambdaがないと、StreamAPIで記述しても冗長になり分かりづらい。
以下、比較のための例。
どっちもStreamAPI使っているけど、冗長な記載がなくなり、シンプル化している。

Lambda適用前

String[] list = {"1", "2", "3", "4", "5"};
Arrays.stream(list).forEachOrdered((value) -> System.out.println(value));


Lambda適用後

String[] list = {"1", "2", "3", "4", "5"};
Arrays.stream(list).forEachOrdered(System.out::println);

見る人が見れば分かる。
疎い人が見ると全く分からない。
JavaでStreamを使うハードルを高くしている要因でもあるが、理解してしまうとこれほど分かりやすいものはない。

これであなたもStreamAPI、Lambda脳に!

使っていると分かるんですが、うまく処理がハマると予想以上に気持ちいいぃぃぃ!!
これが、最高にハイって奴だ!

f:id:suzaku0914:20160331231720p:plain

結構バカにできない。
使っていると本当に気分がいい。
どうやってStreamをつかってやろうかと考えることが楽しみになる

ダークサイド

StreamAPI・Lambdaへの恐れは暗黒面に通じる。
StreamAPI・Lambdaを敬遠することで、記述量は多くなり、多くなった記述は難解になり、難解は属人化を産み、属人化は担当者を苦痛に追い込む。

f:id:suzaku0914:20160416024108j:plain

とはいえ、StreamAPIには暗黒面もある。
やるべきことを1メソッドに一気に取り込みすぎて分かりづらくなるという暗黒面が!
その暗黒面が出てくると、Streamを使っても暗黒面に落ちる。
読み手を考えて書くのは、Stream・Lambda関係なく、意識する目は必ず持ちましょう!

まだまだ

まだStreamAPIは使いこなせていない。
もっと使いこなせるようにしたいが、如何せん、現場でLambdaの記述について討論できる人が身近にいないのが辛い。
本当は直面した問題に対して、すぐに討論できるとフィードバックが早く出来て覚えも早いのだが。。。
だれかと話し合いたい。
読み手を想定して書いてるけど、自分は他人ではないので、たまに他人の視点が欲しい時が多々ある。
職場で仲いい人なんて、出来る気がしない。ぼっち経歴が長いせいか、他人に話かけるのはハードルが高すぎてあきらめちゃうのよね。。。

今後Java8の記法を活性化させる個人案

せっかくJava8環境にいるのだから、Stream・Lambdaは復旧させたい。
個人的に考えた方法

  1. CTOがfor文禁止を宣言する
  2. Stream・Lambdaできる人を複数人投入
  3. あきらめる

選択肢に「あきらめる」を入れるのは重要。
なんでも背負い込みすぎると心が保てない。
とはいえ、やるならやっぱり権力にたよるか、できる人が多くいるほうがいい。
出来ない中に一人だけできる人がいても、全員できる未来には絶対にならない気がするのは我だけだろうか?
ここでも、権力の偉大さを知る。

StreamAPI知らない奴に何と言えばいいのか考え中。。。
今のところ「分かんないからやめろ」って言われたら以下のことを言うつもり

  • あなた技術者ですよね?
  • あなたが勉強してない要因を俺に押し付けるのやめてくれませんか?

書くなって言われたら従いはするけど、ながくその現場に居たいとは思わない。
だって、自分のためにならないんだもの。
キャリアを積む上でも重要だし、なにより奴隷扱いされているみたいで腹が立つのが一番。
今のとこ言われてないけど、言われるのではないかとビクビクしている。
心が弱すぎやね。。。

鉄の意志と鋼の強さ欲しい(黒咲リスペクト!)

f:id:suzaku0914:20160416031714j:plain

彼から学ばなければいけないことは多い!