PR

 しかし、iterateメソッドは無限ストリームであるため、要素数は分かりません。このため、分割が非効率になってしまい、その結果パフォーマンスが悪くなってしまいます。

 つまり、要素数が明確でないストリームは、パラレルストリームに変換するとパフォーマンスが悪化するのです。

 iterateメソッドと同様にgenerateメソッドも無限ストリームになってしまうため、パラレルストリームでは使用すべきではありません。

 これ以外に、ファイルなどから生成するストリームも、パラレルストリームではパフォーマンスが悪化します。

 たとえば、java.nio.file.Filesクラスのlinesメソッドや、java.io.BufferedReaderクラスのlinesメソッドが相当します。これらのクラスはファイル全体を読み込んでからストリームを生成するわけではなく、随時読み込みながらストリームの要素を追加していきます。

 つまり、ファイルの読み始めの時点では要素数が不明であるため、パフォーマンスが悪くなるのです。

 もし、ファイルからストリームを生成する場合には、一度すべてを読み込んでから、パラレルストリームを生成するようにします。たとえば、リスト9のようにファイル内容を保持させるリストを生成してから、ストリームを作ります。

リスト9 ファイルから読み込んだ文字列からパラレルストリームを作成

        List<String> texts = Files.readAllLines(Paths.get(filename));
        
        Stream<String> stream = texts.parallelStream();

 もちろん、この方法では逐次的に読み込みを行うよりも、ヒープの消費量が大きくなります。その点にも注意が必要です。

 また、ストリームの要素数ではないのですが、要素を辿る処理が遅い場合も、パラレルストリームではパフォーマンスが落ちます。

 たとえば、LinkedListオブジェクトからストリームを生成した場合は、ArrayListオブジェクトから生成した場合に比べ、パフォーマンスがかなり悪くなります。

 このように、ストリームをどのようにして生成するかによって、パフォーマンスは大きく異なるのです。