OK、説明できるかどうか見てみましょう。
Javaイテレーター(Hadoopから)をScalaストリームにラップするコードがあります。これにより、直接制御できないクライアントコードによって、Javaイテレーターを複数回読み取ることができる可能性があります。このStreamで最後に行われるのは、reduce()操作です。Streamは、すでに表示されているすべてのアイテムを記憶しています。残念ながら、状況によってはイテレータが非常に大きくなるため、すべてのアイテムをイテレータに格納すると、メモリ不足エラーが発生します。ただし、一般に、クライアントコードが複数の反復機能を必要とする状況は、メモリを破壊するイテレータと同じではありません。そのような場合が存在する場合、それは私の問題ではありません。
私が確実にしたいのは、メモ化機能を必要とするコードには提供できるが、それを必要としないコード(特に、ストリームをまったく見ないコード)には提供できないことです。
Streamのreduce()のコードは、Streamのすでにアクセスされた部分のGCが発生することを可能にする方法で記述されていることを示しています。削減します。ですから、これが実際に起こることを確認できれば、大丈夫です。しかし実際には、これが確実に行われるようにするにはどうすればよいでしょうか。特に、関数Aがストリームを作成して関数Bに渡し、関数Bがストリームを関数Cに渡し、関数Cがreduce()を呼び出す場合、関数A、B、およびCにあるストリームへの参照はどうでしょうか。 ?これらすべての場合、呼び出しは必ずしも末尾再帰である必要はありませんが、3つの関数のいずれでもストリームをそれ以上使用することはありません。JVMは、reduce()が呼び出されたときに関数A、B、およびCからの参照カウントが0になるように十分にスマートであり、GCが発生する可能性がありますか?基本的に、これは、JVMが関数Aで、アイテムに対して最後に行うことは関数Bの呼び出しであることに気付くため、Bを呼び出すと同時に自身のハンドルを削除することを意味します。
これが適切に機能する場合、A、B、またはCにアイテムを保持するローカル変数がある場合にも機能しますか?(これも、後で使用されません。)これは、ローカル変数を使用せずにこれを適切にコーディングするのがかなり難しいためです。