Поток против просмотров против итераторов
Каковы различия между потоками, представлениями (SeqView) и итераторами в Scala? Это мое понимание
- Они все ленивые списки.
- Потоки кэшируют значения.
- Итераторы можно использовать только один раз? Вы не можете вернуться к началу и снова оценить значение?
- Значения представления не кэшируются, но вы можете оценивать их снова и снова?
Так что, если я хочу сэкономить место в куче, я должен использовать итераторы (если я не буду пересматривать список снова) или представления? Благодарю.
1 ответ
Во-первых, все они не строгие. Это имеет особое математическое значение, связанное с функциями, но, в основном, означает, что они вычисляются по требованию, а не заранее.
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
после применения преобразований или оставьте его в качестве представления, если ожидается, что будет извлечено только несколько элементов, по сравнению с общим размером представления.