1. ホーム
  2. java

[解決済み] ストリームでJava 8のforeachループを使用して次のアイテムに移動する

2022-04-20 17:46:09

質問

Java 8 の foreach のストリームがループの中で次のアイテムに移動しようとする問題があります。のようなコマンドを設定することができません。 continue; のみです。 return; が動作しますが、この場合はループから抜けてしまいます。ループ内の次のアイテムに移動したい。どうすればいいのでしょうか?

例(動作しない)。

try(Stream<String> lines = Files.lines(path, StandardCharsets.ISO_8859_1)){
            filteredLines = lines.filter(...).foreach(line -> {
           ...
           if(...)
              continue; // this command doesn't working here
    });
}

例(動作中)。

try(Stream<String> lines = Files.lines(path, StandardCharsets.ISO_8859_1)){
    filteredLines = lines.filter(...).collect(Collectors.toList());
}

for(String filteredLine : filteredLines){
   ...
   if(...)
      continue; // it's working!
}

解決方法は?

使用方法 return; は正常に動作します。 ループ全体が終了するのを防ぐことはできません。 の現在の反復実行を停止するだけです。 forEach ループを使用します。

次の小さなプログラムを試してみてください。

public static void main(String[] args) {
    ArrayList<String> stringList = new ArrayList<>();
    stringList.add("a");
    stringList.add("b");
    stringList.add("c");

    stringList.stream().forEach(str -> {
        if (str.equals("b")) return; // only skips this iteration.

        System.out.println(str);
    });
}

出力します。

a

c

がどのように return; に対して実行されます。 b の繰り返しですが c は次のイテレーションで問題なく印刷されます。

なぜこれがうまくいくのでしょうか?

最初にこの動作が直感的でないように見えるのは、私たちが return 文はメソッド全体の実行を中断させます。 ですから、この場合、私たちは main メソッドの実行が全体として停止する。

しかし、理解しておかなければならないのは、次のようなラムダ式であることです。

str -> {
    if (str.equals("b")) return;

    System.out.println(str);
}

...本当に、それ自身の別個のメソッドとして考慮する必要があります。 main メソッドの中にあるにもかかわらず、便利なものです。ですから、実際には return 文はラムダ式の実行を停止させるだけである。

次に理解しなければならないのは、そのことです。

stringList.stream().forEach()

...は、実際には、反復ごとにラムダ式を実行する通常のループを隠しているだけです。

この2点を考慮すると、上記のコードは以下のように等価に書き換えることができます(あくまで教育目的です)。

public static void main(String[] args) {
    ArrayList<String> stringList = new ArrayList<>();
    stringList.add("a");
    stringList.add("b");
    stringList.add("c");

    for(String s : stringList) {
        lambdaExpressionEquivalent(s);
    }
}

private static void lambdaExpressionEquivalent(String str) {
    if (str.equals("b")) {
        return;
    }

    System.out.println(str);
}

このquot;less magic"コードに相当するものであれば、スコープが return 文がより明確になります。