Во-первых, они все не строгие . Это имеет особое математическое значение, связанное с функциями, но, в основном, означает, что они вычисляются по требованию, а не заранее.
Stream
действительно ленивый список. На самом деле в Scala Stream
- это List
, чье tail
- это lazy val
. После вычисления значение остается вычисленным и используется повторно. Или, как вы говорите, значения кэшируются.
Iterator
можно использовать только один раз, поскольку он является указателем обхода в коллекции, а не коллекцией сам по себе. Что делает его особенным в Scala, так это тот факт, что вы можете применить преобразование, например map
и filter
, и просто получить новый Iterator
, который будет применять эти преобразования только при запросе следующего элемента.
Scala использовался для предоставления итераторов, которые могли быть сброшены, но это очень сложно поддерживать в общем виде, и они не сделали версию 2.8.0.
Представления предназначены для просмотра так же, как представление базы данных. Это серия преобразований, которые применяются к коллекции для создания «виртуальной» коллекции. Как вы сказали, все преобразования повторно применяются каждый раз, когда вам нужно извлечь из него элементы.
И Iterator
, и представления имеют отличные характеристики памяти. Stream
это хорошо, но в Scala основным преимуществом является написание бесконечных последовательностей (особенно рекурсивно определенных последовательностей). Один может избежать хранения всего Stream
в памяти, хотя, убедившись, что вы не сохраняете ссылку на его head
(например, используя def
вместо val
определить Stream
).
Из-за штрафов, понесенных представлениями, обычно следует force
использовать его после применения преобразований или сохранять его в качестве представления, если ожидается, что когда-либо будет выбрано только несколько элементов, по сравнению с общим размером представления.