Я только что прочитал, что время выполнения операции добавления для List
(: +) растет линейно с размером List
.
Присоединение к a List
кажется довольно обычной операцией. Почему идиоматический способ сделать это состоит в том, чтобы предварительно добавить компоненты, а затем перевернуть список? Это также не может быть ошибкой проекта, поскольку реализация может быть изменена в любой момент.
С моей точки зрения, и добавление, и добавление должны быть O (1).
Есть ли законная причина для этого?
List[T]
Предполагается, что вы используете его так, как если бы вы работали на чистом функциональном языке - как правило, работая с головы с деконструкцией и приставками.Ответы:
Я немного расширю свой комментарий. Структура
List[T]
данных отscala.collection.immutable
оптимизирована для работы так, как работает неизменный список в более чисто функциональном языке программирования. У него очень быстрое время предварительной подготовки , и предполагается, что вы будете работать над головой почти весь свой доступ.Неизменяемые списки получают очень быстрое время предопределения из-за того, что они моделируют свои связанные списки как серию «cons-ячеек». Ячейка определяет одно значение и указатель на следующую ячейку (классический стиль односвязного списка):
Когда вы переходите к списку, вы на самом деле просто делаете одну новую ячейку, а остальная часть существующего списка указывается на:
Поскольку список неизменен, вы можете сделать это без фактического копирования . Нет опасности того, что старый список изменится и все значения в вашем новом списке станут недействительными. Однако вы теряете возможность иметь изменяемый указатель на конец вашего списка как компромисс.
Это очень хорошо подходит для рекурсивной работы со списками. Допустим, вы определили свою собственную версию
filter
:Это рекурсивная функция, которая работает исключительно с заголовка списка и использует преимущества сопоставления с образцом через :: extractor. Это то, что вы часто видите в таких языках, как Haskell.
Если вы действительно хотите быстрое добавление, Scala предоставляет множество изменяемых и неизменных структур данных на выбор. На изменчивой стороне, вы можете посмотреть
ListBuffer
. Кроме того ,Vector
изscala.collection.immutable
имеет быстрое время добавления.источник
else
не бесконечный цикл? Я думаю, что это должно быть что-то вродеx::deleteIf(xs)(f)
.head
иtail
доступ к этому виду списка очень быстрый - быстрее, чем использование любой карты или массива на основе хеша - это отличный тип для рекурсивных функций. Это одна из причин, почему списки являются базовым типом в большинстве функциональных языков (например, Haskell или Scheme)List
s и добавления / добавления).