Поток против просмотров против итераторов - PullRequest
131 голосов
/ 01 марта 2011

Чем отличаются потоки, представления (SeqView) и итераторы в scala? Это мое понимание:

  • Это все ленивые списки.
  • Потоки кэшируют значения.
  • Итераторы можно использовать только один раз? Вы не можете вернуться к началу и снова оценить значение?
  • Значения представления не кэшируются, но вы можете оценивать их снова и снова?

Так что, если я хочу сэкономить место в куче, я должен использовать итераторы (если я не буду пересматривать список снова) или представления? Благодарю.

1 Ответ

178 голосов
/ 01 марта 2011

Во-первых, они все не строгие . Это имеет особое математическое значение, связанное с функциями, но, в основном, означает, что они вычисляются по требованию, а не заранее.

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 использовать его после применения преобразований или сохранять его в качестве представления, если ожидается, что когда-либо будет выбрано только несколько элементов, по сравнению с общим размером представления.

...