Поток против просмотров против итераторов

136

Каковы различия между потоками, представлениями (SeqView) и итераторами в Scala? Это мое понимание

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

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

ОРК
источник
7
Я уже отвечал на это раньше, но как его найти? вздох ...
Даниэль С. Собрал

Ответы:

182

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

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

Даниэль С. Собрал
источник
10
Iteratorэто также очень удобно для исследования бесконечности, и я обычно предпочитаю их потокам, где это возможно. Реальное преимущество в потоках заключается в том, что ранее полученные значения кэшируются, что является серьезным благом при попытке реализовать что-то вроде последовательности Фибоначчи, которая определяется в терминах предыдущих значений.
Кевин Райт
5
Фибоначчи - не совсем идеальный пример, так как ему нужны только последние 2 предыдущих значения, а сохранение всего потока - пустая трата времени. Функция Аккермана, вероятно, является каноническим примером.
Юрген Штробель
4
@ JürgenStrobel Ackermann приведет к паршивой производительности, поскольку индексированный доступ к потокам равен O (n). Но я согласен с Фибоначчи.
Даниэль С. Собрал,
9
О верно. Это делает Stream плохим выбором для любого подхода к кешированию.
Юрген Штробель
7
Этот ответ очень ясен, он должен быть частью документации ... о, на самом деле это так! Спасибо Даниэль docs.scala-lang.org/tutorials/FAQ/stream-view-iterator.html
Свенд