Почему в стандартной библиотеке scala нет неизменных массивов? - PullRequest
37 голосов
/ 28 января 2011

Scala имеет все виды неизменяемых последовательностей, таких как List, Vector и т. Д. Я был удивлен, когда не нашел реализации неизменяемой индексированной последовательности, подкрепленной простым массивом (Vector кажется слишком сложным для моих нужд).

  • Есть ли для этого конструктивная причина? Я не смог найти хорошее объяснение в списке рассылки.

  • Есть ли у вас рекомендации для неизменяемой индексированной последовательности, которая имеет почти такие же характеристики, что и массив? Я рассматриваю скаляр ImmutableArray, но у него, например, есть некоторые проблемы с магистралью scala.

Спасибо

Ответы [ 5 ]

31 голосов
/ 28 января 2011

Вы можете преобразовать ваш массив в последовательность.

val s: Seq[Int] = Array(1,2,3,4)

Массив будет неявно преобразован в WrappedArray.А так как тип Seq, операции обновления больше не будут доступны.

19 голосов
/ 28 января 2011

Итак, давайте сначала сделаем различие между интерфейсом и классом. Интерфейс является проектом API, а класс - реализацией такого API.

Интерфейсы в Scala имеют одинаковое имя и различный пакет, чтобы различать их в отношении неизменности: Seq, immutable.Seq, mutable.Seq.

С другой стороны, классы обычно не имеют общего имени. List - это неизменяемая последовательность, а ListBuffer - изменяемая последовательность. Существуют исключения, например HashSet, но это просто совпадение в отношении реализации.

Теперь, и Array не является частью коллекции Scala, являясь Java-классом, но его оболочка WrappedArray ясно показывает, где он будет отображаться: как изменяемый класс.

Интерфейс , реализованный WrappedArray, равен IndexedSeq, который существует как изменчивый и неизменный признаки.

immutable.IndexedSeq имеет несколько реализующих классов, включая WrappedString. Класс общего использования, реализующий его, однако, Vector. Этот класс занимает ту же позицию, которую класс Array занимал бы в изменчивой части.

Теперь, использование Vector не сложнее, чем использование Array, поэтому я не знаю, почему вы называете это сложным.

Возможно, вы думаете, что это слишком много внутренне, и в этом случае вы ошибаетесь. Все хорошо спроектированные неизменяемые классы persistent , потому что использование неизменяемой коллекции означает создание ее новых копий, поэтому их необходимо оптимизировать для этого, что и делает Vector.

11 голосов
/ 28 января 2011

В основном потому, что в Scala нет никаких массивов.То, что вы видите, это java-массивы с несколькими методами, которые помогают им вписаться в API-интерфейс коллекции.

Все остальное не будет массивом с его уникальным свойством не подвергаться стиранию типов или поврежденныхдисперсия.Это был бы просто другой тип с индексами и значениями.Scala имеет это, оно называется IndexedSeq, и если вам нужно передать его в виде массива в какой-либо сторонний API, вы можете просто использовать .toArray

1 голос
/ 28 января 2011

Цель класса scala Array - предоставить механизм для доступа к способностям массивов Java (но без ужасного решения Java о проектировании , позволяющего использовать коварианты вего система типов).Java-массивы являются изменяемыми, следовательно, такие же, как и в стандартной библиотеке Scala.

Предположим, что в библиотеке был еще один класс immutable.Array, но компилятор также использовал массив Java в качестве базовой структуры (для эффективности / скорости).Следующий код затем скомпилируется и запустится:

val i = immutable.Array("Hello")
i.asInstanceOf[Array[String]](0) = "Goodbye"
println( i(0) ) //I thought i was immutable :-(

То есть массив действительно будет изменяемым.

0 голосов
/ 16 ноября 2016

Проблема с массивами в том, что они имеют фиксированный размер.Операции по добавлению элемента в массив или его удалению из него отсутствуют.

Вы можете оставить массив, который, как вы думаете, будет достаточно длинным в качестве резервного хранилища, «тратя» память, которой вы не являетесьиспользуя, отслеживайте последний использованный индекс и копируйте в больший массив, если вам нужно дополнительное пространство.Это копирование O(N) очевидно.

Изменение одного элемента также O(N), так как вам нужно будет копировать весь массив.Не существует структурного совместного использования, которое является основой для функциональных структур данных.

Вы также можете выделить дополнительный массив для «переполненных» элементов и каким-то образом отслеживать ваши массивы.В этот момент вы находитесь на пути к переизобретению Vector.

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

Это оставляет только вариант использования носителя данных фиксированного размера с фиксированным размером, и этот вариант использования является относительно редким.В большинстве случаев лучше использовать с List, Stream или Vector

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...