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

116

Каковы различия между Streams, Views (SeqView) и Итераторами в scala? Это мое понимание:

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

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

Теги:
scala-collections

1 ответ

169
Лучший ответ

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

Stream - это ленивый список. Фактически, в Scala a Stream является List, чей tail является lazy val. После вычисления значение остается вычисленным и повторно используется. Или, как вы говорите, значения кэшируются.

An Iterator может использоваться только один раз, потому что это указатель обхода в коллекцию, а не сама по себе коллекция. Особенностью Scala является то, что вы можете применить преобразование, например map и filter, и просто получить новый Iterator, который будет применять эти преобразования только при запросе следующего элемента.

Scala используется для предоставления итераторов, которые могут быть reset, но это очень сложно поддерживать в общем виде, и они не сделали версию 2.8.0.

Представления предназначены для просмотра так же, как и представление в базе данных. Это серия преобразований, которая применяется к коллекции для создания "виртуальной" коллекции. Как вы сказали, все преобразования повторно применяются каждый раз, когда вам нужно извлекать из него элементы.

Оба Iterator и представления имеют отличные характеристики памяти. Stream хорош, но в Scala его основное преимущество - писать бесконечные последовательности (в частности, рекурсивно определенные последовательности). Однако можно избежать сохранения всего Stream в памяти, если вы не сохраните ссылку на его head (например, используя def вместо val, чтобы определить Stream).

Из-за штрафов, понесенных представлениями, обычно следует force его после применения преобразований или сохранить его как представление, если ожидается, что только несколько элементов будут получены, по сравнению с общим размером представления.

  • 10
    Iterator также очень удобен для исследования бесконечности, и я обычно предпочитаю их потокам, где это возможно. Реальное преимущество в потоках заключается в том, что ранее полученные значения кэшируются, что является серьезным благом при попытке реализовать что-то вроде последовательности Фибоначчи, которая определяется в терминах предыдущих значений.
  • 4
    Фибоначчи - не совсем идеальный пример, так как ему нужны только последние 2 предыдущих значения, а сохранение всего потока - пустая трата времени. Функция Аккермана, вероятно, является каноническим примером.
Показать ещё 5 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню