LoginSignup
80
58

More than 3 years have passed since last update.

もう無駄にfor文書くのやめようや...。

Last updated at Posted at 2021-04-22

はじめに

Java8以降で何も考えずに「for文を用いた繰り返し処理」を使うのはやめましょう。
書き手、読み手にとっても良くないし、特別な理由がなければ積極的に新しい技術を使うべきです。
良くない理由としては様々ありますが、主な理由としては以下の点が挙げられます。

  • 処理の内容をパッと見て把握しづらい
  • 不具合のトリガーになる
  • ソースコードの肥大化

では具体的な例を次に示します。

具体例1

NGパターン

例1
        List<String> nameList = Arrays.asList("Taro", "Jiro", "Saburo", "Shiro", "Goro");
        for (int i = 0; i < nameList.size(); i++) {
            System.out.println(nameList.get(i));
        }

OKパターン

例2
        List<String> nameList = Arrays.asList("Taro", "Jiro", "Saburo", "Shiro", "Goro");
        // ① せめてこちらのパターン
        nameList.forEach(name -> System.out.println(name));
        // ② こっちだとなおよし
        nameList.forEach(System.out::println);

こちらはnameListの値を繰り返し取得して表示するだけの単純なコードになっています。
ではNGパターンで記載している例1が何故NGなのかを説明します。
従来のfor文の書式は次のような構成になっていますが、

for文の書式
        for (初期化式 条件式 変化式) {
            実行する処理
        }

私はこの書式でコードを書く際は

私「初期化式は i=0; だったかな?、i=1; だったかな?」
私「条件式は初期化式を i=0; にしたから、i <= nameList.size(); かな?」
私「ちがうちがう。i < nameList.size(); やわ!」

などを毎回考えてしまいます。。

人によっては、

「これくらいは一瞬で考えれる。」
「絶対間違えへんわ!」

のような方も、もちろんいらっしゃると思いますが、私のように毎回「うーん。」と考える人がいるのも事実です。
したがって、これらを毎回考えること自体が、うっかりミスのトリガーになると考えています。
こちら の書籍ではこの書式を「自殺点パターン」と呼んでいましたが、まさにその通りですね。絶対いつか間違える。。

一方、例2のforEach()を使うパターンだと

  • 一行で簡潔に書ける!
  • 条件式などを記載する必要も無い!
  • 読み手も理解しやすい!

皆で幸せになれますね。
②のパターンでは「メソッド参照」を用いて①より簡潔に記載しています。

※ メソッド参照については本記事では解説しません。
※ 気になる方は分かりやすく説明して頂いている方の記事がありますので、こちらを参照してくさい。

具体例2

次の例は1~10の数値が格納されているnumListの中で、偶数の合計を表示するコードになります。

NGパターン

例3
        List<Integer> numList = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        int evenSum = 0;
        for (int i = 0; i < numList.size(); i++) {
            if (numList.get(i) % 2 == 0) {
                evenSum += numList.get(i);
            }
        }
        System.out.println(evenSum); // -> 30

OKパターン

例4
        List<Integer> numList = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        int evenSum = numList.stream()
                .mapToInt(Integer::intValue)
                .filter(num -> num % 2 == 0)
                .sum();
        System.out.println(evenSum); // -> 30

NGパターンの理由としては例1の時と同じ理由ですが、OKパターンの良い点は上から下へ順番に読むだけで処理が理解できることです。実際に読んでみると、

  1. マップ処理を行い
  2. 偶数の値のみフィルタして
  3. それらを合計する

やりたいことを上から順番に記載していくだけなので、「コード = 設計書」のような形になります。
やっぱり、従来のfor文で書くより良いですね。

参考文献

さいごに

Javaは現在(2021/04/21時点)では16までリリースしており、より便利な形へと日々進化しています。
面倒という理由のみで、新しい技術を使わないのは書き手の怠慢だし、本日紹介した構成はjava8以降なら使えますので皆で頑張りましょうー。(Java8のリリースは2014/03)

80
58
13

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
80
58