lambdaについて調べてみた forEach編 その1

【概要】

前回まではラムダを使って関数型インターフェイス
オブジェクトを生成していました。

今回はforEachメソッドについて調べてみました。

【List/Set】

まずはList/SetでのforEachを見ていきます。

[List]
    public static void main(final String[] args) {

        final List<String> valueList = new ArrayList<>();
        valueList.add("one");
        valueList.add("two");
        valueList.add("three");

        // forEachメソッド
        valueList.forEach(value -> System.out.println(value));

        // 今までのfor文
        for (final String value : valueList) {
            System.out.println(value);
        }
   }

forEachの実行結果とfor文の実行結果は同じです。

forEachメソッドはリストが保持している各要素を
ラムダのパラメータとして渡します。

今回のサンプルではvalueListに入っている値が
valueに渡されて、データの数だけ処理が実行されます。

メソッド参照を使うと

    valueList.forEach(System.out::println);

で同じように処理が行われます。

[Set]

続いてSetですが、Listと変わりません。

    public static void main(final String[] args) {
        final Set<String> valueSet = new LinkedHashSet<>();
        valueSet.add("one");
        valueSet.add("two");
        valueSet.add("three");
        valueSet.forEach(System.out::println);
   }

【Map】

Mapについてはぱっと思いつくのはSetへの変換です。

    public static void main(final String[] args) {

        final Map<String, Integer> valueMap = new HashMap<>();
        valueMap.put("one", 1);
        valueMap.put("two", 2);
        valueMap.put("three", 3);

        valueMap.entrySet().forEach(
                entry -> 
                    System.out.println(entry.getKey() + "-" + entry.getValue()));
   }

entrySetでMap.EntryクラスのSetを取得。
取得したSetに対してforEachメソッドを呼び出します。

これでも良いのですが、MapインターフェイスにもforEachメソッドが追加されています。
Map#forEachを使えば、Setに変換する必要がありません。

    public static void main(final String[] args) {

        final Map<String, Integer> valueMap = new HashMap<>();
        valueMap.put("one", 1);
        valueMap.put("two", 2);
        valueMap.put("three", 3);

        valueMap.forEach((key, value) -> System.out.println(key + "-" + value));
   }

これでSetに変換する方法と同じ結果になります。

List/SetのforEachのパラメータはConsumerですが、
MapのforEachはBiConsumerなのでパラメータを2つ受け取っています。

【Array】

    public static void main(final String[] args) {

        final String[] valueArray = { "one", "two", "three" };
        Arrays.asList(valueArray).forEach(System.out::println);
    }

配列は流石にListへ変換しないと無理です。

【for文との違い】

forEachを使うと一時変数の型宣言を省略できて、
for文を書くより簡潔にかけます。

forEachは関数型インターフェイスのオブジェクトを受け取ります。
なので、繰り返しさせる処理を分岐させることができます。

    Consumer<String> outputLambda = null;
    if (isNeedLn) {

        outputLambda = System.out::println;
    } else {
        
        outputLambda = System.out::print;
    }
    valueList.forEach(outputLambda);

関数をオブジェクトを扱うことに慣れていないので、
こういう分岐のさせ方はどうなんだろうかと
思ったりもしますが、できないことはないです。