【プログラミング】Java8のstreamとfilterのイメージ掴み

Java

割と長くJavaには触っているけど、Java8以降の言語仕様には

ほとんど触れてきていないんだよなぁ…

割と自分自身の経験浅な部分ではあるので、復習も兼ねてエントリに起こそうと思いました。

はじめに

おそらくこのエントリをご覧になる方は、「streamとかよくわからん… 」「filterのイメージがつかみづらい」「別にstream使わなくていいんじゃない?」と思いつつも、なんか悔しいから検索された末にたどり着かれたのかと思います。ただ、結論としては以下の通りで、

  • Collectionを取り扱いやすくしているだけ!
  • Excelのフィルタ機能をイメージすれば動作イメージを持ちやすい!
  • 繰り返しを明示的に書く必要がなくなり、プログラムがコンパクト化される!

というかんじです。

こんな人向け

  • 長くJavaには触れているが、Javaのバージョンアップの恩恵に与れていない人
  • 他人のイメージを覗いてみたい人

とっととサンプルコードを見たい・使い方を知りたい方は、こちらからサンプルコードをご覧ください。旧来の書き方も一緒に書いてます。(Java1.4以前は知らんですよ?)

stream

streamとは

辞書を引くと「モノの流れ」と出てきますが、プログラムで使う時は専ら、連なったデータの流れを指しているイメージがあります。今回のstreamは、Collectionに対する操作を効率よく行うためのオブジェクトとなります。(Java APIでは「順次および並列の集約操作をサポートする要素のシーケンスです」とあります。

Stream (Java Platform SE 8)

イメージ図

Listオブジェクトに対してstreamを実行したときに、どういったデータ構造になるのかなぁ?というのを自身が理解しやすい形ではありますがイメージ図にしてみました。

上図のように、streamを使うことで一つの連続したデータにするイメージで理解しました。

filter

filterとは

指定された要素に絞り込むときに使われる単語なイメージです。(主観)

Stream (Java Platform SE 8)

APIにも「指定された述語に一致するものから構成されるストリームを返します」って記載がありますね。

イメージ図

streamの時と同様に、こちらもイメージ図を作ってみました。streamのデータを基にして書いてます。

filter後のイメージ。連続データなので本来は「りんご」ー「ぱんだ」間のスキマはないけどイメージを重視してます。
ちなみに細かい話になりますが、上のstreamと下のstreamは別オブジェクトになります。(APIより)

filterはExcelをよく使う人なら割とイメージがしやすいと思っています。表を作って絞り込みとかをする人はもっとつかみやすいと思います。Excelにもフィルタ機能がありますが、あてはまる値にチェック入れて「OK」って押せば、選んだ行だけになりますよね。イメージとしてはそれと同じでいいと思います。Excelのイメージ図も貼っておきますね。

フィルタをかける前のリスト
「ん」を含む単語だけ選択してます。(Javaのfilterで設定する条件と類似)
「OK」押すと選択した単語の行だけ表示されます。

サンプルコード

リストのフィルタ実験コード

サンプルコード使ってフィルタ動作の確認をしていこうと思います。「要素に”K”が含まれるもののみ、抽出して表示する。」という仕様の基に作成したサンプルコードです。

【サンプルコード】

public class LearningStream {
public static void main(String[] args) {
    // 大文字"K"を含む文字列が設定されている要素のみを扱いたい。
    // →「YoKohama」と「Kyoto」がListに残ってほしい要素となります。
    String[] strArray = {"YoKohama", "Nagoya", "Osaka", "Kyoto", "kobe"};
    List<String> streamLearningList = Arrays.asList(strArray);

    streamLearningList.stream()
                      .filter(x -> (x.indexOf("K") != -1))    //…P-1
                      .forEach(x -> System.out.println(x));
 }
 }

【実行結果】

YoKohama
Kyoto

「//…P-1」の箇所でフィルタ条件を指定して、条件に一致した要素のみ残すようにしています。直後のforEachではフィルタした要素の出力を行います。(本エントリとは別物なので詳細は省略)

実行結果については、小文字の”k”は条件に一致しないため除外されるので、”Osaka”、”kobe”が含まれない出力結果となります。

(おまけ)streamを使えないバージョンのサンプルコード

Java8より前のバージョンだと、どう書くかなぁと思ったのでこちらも。行いたい操作は上のstream→filterと一緒です。

public class LearningStream2 {
public static void main(String[] args) {
    String[] strArray = {"YoKohama", "Nagoya", "Osaka", "Kyoto", "kobe"};
    List<String> olderList = new ArrayList<>();
    for (String elem : strArray) {
        if (elem.indexOf("K") != -1) {
            olderList.add(elem);
        }
    }
    for (String listElem : olderList) {
        System.out.println(listElem);
    }
}

最後に

streamとfilterを学んだ上のまとめとしては、

  • Collectionを取り扱いやすくしているだけ!
  • Excelのフィルタ機能をイメージすれば動作イメージを持ちやすい!
  • 繰り返しを明示的に書く必要がなくなり、プログラムがコンパクト化される!

Java8もリリースされてから5年以上経過しているので、Javaの案件を探す上でこの辺の知識はmustになっているんではなかろうかと、色々面談を受けてみて思うわけです。(書類で落ちるケースも当然ありますからね)

Java9以降は、またガラッと様変わりしているようですが(リリーススパンもエライ早くなってますし)、バージョンが新しくなるとプログラム構文も洗練化されていくので便利なのは理解できているので、キャッチアップの速度上げねばなぁとつくづく思いますね。

コメント

タイトルとURLをコピーしました