回答:
これは、ショートサーキットと呼ばれるストリームの最適化です。基本的に、最終的な結果がわかっている場合は実行する意味がないため、ストリームallMatch
で不要な中間操作が実行されないようになります。
これが起こったようです:
take"Fred"
peek("Fred")
evaluate("Fred".startsWith("F"))
decide whether the result of allMatch() is known for sure: Not yet
take"Jim"
peek("Jim")
evaluate("Jim".startsWith("F"))
decide whether the result of allMatch() is known for sure: Yes
ときに"Jim".startsWith("F")
評価され、結果がallMatch(s -> s.startsWith("F"))
特定のために知られています。後"Jim"
にパイプラインに入る値は関係ありません。「F」で始まるすべての値はfalseであることがわかります
これはpeek
/のallMatch
組み合わせに固有のものではなく、複数の中間および端子短絡操作があります。java.util.stream
パッケージのドキュメントの状態:
さらに、一部の操作は短絡操作と見なされます。中間演算は、無限の入力が提示されたときに結果として有限のストリームが生成される可能性がある場合、短絡です。端末操作は、無限の入力が提示されたときに有限の時間で終了する可能性がある場合、短絡です。パイプラインで短絡操作を行うことは、無限ストリームの処理が有限時間で正常に終了するために必要ですが、十分ではありません。
例のように、これを有限ストリームに拡張し、操作を短絡することで、不要なパイプラインステップの実行を回避できます。
allMatch()のJavaドキュメントによると:
このストリームのすべての要素が指定された述語と一致するかどうかを返します。結果の決定に必要でない場合、すべての要素の述語を評価しない場合があります。ストリームが空の場合、{@ code true}が返され、述語は評価されません。
@apiNote
このメソッドは、ストリームの要素に対する述語の普遍的な数量化を評価します(すべてのx P(x)に対して)。ストリームが空の場合、数量化は空虚に満たされていると言われ、常に{@code true}になります(P(x)に関係なく)。
ストリームのすべての要素が提供された述語と一致するか、ストリームが空の場合、このストリームの要素に適用する述語@return {@code true}、それ以外の場合は{@code false}
あなたの場合:
1-
p(x) : s -> s.startsWith("F")
X : "Fred"
result : X P(X) = true
2-
p(x) : s -> s.startsWith("F")
X : "Jim"
result : X P(X) = false
XP(X)= falseであるため、これ以上の評価は行われません。
boolean result = Arrays.asList("Fred", "Finda", "Fish")
.stream()
.peek(System.out::println)
.allMatch(s -> s.startsWith("F"));
System.out.println("Result "+result);
出力は:
Fred
Finda
Fish
Result true
ここでは、各要素からxP(x)= trueであるため、ストリームは完全に処理されました