Primeiro, eles são todos não rigorosos . Isso tem um significado matemático específico relacionado às funções, mas, basicamente, significa que elas são computadas sob demanda e não antecipadamente.
Stream
é realmente uma lista preguiçosa. De fato, em Scala, a Stream
é um List
cujo tail
é a lazy val
. Uma vez calculado, um valor permanece calculado e é reutilizado. Ou, como você diz, os valores são armazenados em cache.
Um Iterator
só pode ser usado uma vez porque é um ponteiro transversal para uma coleção, e não uma coleção em si. O que o torna especial em Scala é o fato de que você pode aplicar de transformação, como map
e filter
e simplesmente obter um novo Iterator
que só irá aplicar essas transformações quando você perguntar para o próximo elemento.
O Scala costumava fornecer iteradores que poderiam ser redefinidos, mas isso é muito difícil de suportar de uma maneira geral, e eles não criaram a versão 2.8.0.
As visualizações devem ser vistas como uma exibição de banco de dados. É uma série de transformação que se aplica a uma coleção para produzir uma coleção "virtual". Como você disse, todas as transformações são reaplicadas sempre que você precisar buscar elementos nela.
Ambas as Iterator
visualizações e têm excelentes características de memória. Stream
é bom, mas, em Scala, seu principal benefício é escrever sequências infinitas (particularmente sequências definidas recursivamente). Um pode evitar manter todas as Stream
na memória, no entanto, por ter certeza que você não manter uma referência ao seu head
(por exemplo, usando def
em vez de val
definir o Stream
).
Por causa das penalidades incorridas pelas visualizações, geralmente force
é necessário após a aplicação das transformações, ou mantê-la como uma visualização, se é esperado que apenas alguns elementos sejam buscados, em comparação com o tamanho total da visualização.