В коллекциях Scala постоянно проводят различие между неизменяемыми и изменяемыми коллекциями. Изменяемые (mutable) коллекции могут быть изменены или дополнены. Это означает, что вы можете изменять, добавлять или удалять её элементы. Неизменяемые (Immutable) коллекции, напротив, никогда не меняются. У них есть операции, имитирующие добавления, удаления или обновления, но эти операции каждый раз будут возвращать новую коллекцию и оставлять старую коллекцию без изменений.
Все варианты коллекции находятся в пакете scala.collection
либо в одном из его подпакетов mutable
или immutable
. Большинство коллекции, которые необходимы для работы с клиентским кодом, существуют в трех вариантах,
те которые находятся в пакетах scala.collection
, scala.collection.immutable
или scala collection.mutable
. У каждого варианта свои особенности в работе, связанные с разным подходом к обработке изменений.
Каждая коллекция в пакете scala.collection.immutable
гарантированно будет неизменяемой. Такая коллекция никогда не изменится после ее создания. Поэтому, вы, можете положиться на факт того, что повторный доступ к значениям коллекции в любой момент времени приведет к одному и томуже результату.
Известно, что у коллекции в пакете scala.collection.mutable
есть операции, которые изменяют саму коллекцию. Поэтому, работая с изменяемой коллекцией вам нужно четко понимать, где и когда в нее вносятся изменения.
Коллекция в пакете scala.collection
может быть как изменяемой, так и неизменяемой.
Например, collection.IndexedSeq[T]
является базовой для обоих коллекций collection.immutable.IndexedSeq[T]
и
collection.mutable.IndexedSeq[T]
Как правило, базовые коллекции пакета scala.collection
поддерживают операции преобразования, затрагивающие всю коллекцию, неизменяемые коллекции пакета scala.collection.immutable
обычно добавляют операции добавления или удаления отдельных элементов, а изменяемые коллекции пакета scala.collection.mutable
обычно добавляют к базовому интерфейсу операции модификации элементов, основанные на побочных эффектах.
Еще одним отличием базовой коллекции от неизменяемой является то, что пользователи неизменяемой коллекции имеют гарантию, что никто не сможет изменить коллекцию, а пользователи базовой коллекции лишь обещают не менять ее самостоятельно. Даже если тип такой коллекции не предоставляет никаких операций для модификации коллекции, все равно возможно, что эта коллекция, может быть изменена какими-либо сторонними пользователями.
По умолчанию Scala всегда выбирает неизменяемые коллекции. Например, если вы просто пишете Set
без префикса или импортируете Set
откуда-то, вы получаете неизменяемый Set, а если вы пишете Iterable
- получите неизменяемую Iterable коллекцию, потому что такие связки прописаны по умолчанию, в пакетеscala
. Чтобы получить изменяемую версию необходимо явно написать collection.mutable.Set
или collection.mutable.Iterable
.
Полезное соглашение, если вы хотите использовать как изменяемую, так и неизменяемую версию коллекций - импортируйте только пакет collection.mutable
.
import scala.collection.mutable
Тогда указание типа Set
без префикса по-прежнему будет относиться к неизменяемой коллекции, в то время как mutable.Set
буде относиться к переменному аналогу.
Последним пакетом в иерархии коллекций является scala.collection.generic
. Этот пакет содержит строительные элементы для абстрагирования поверх конкретных коллекций.
Для удобства и обратной совместимости некоторые важные типы имеют псевдонимы в scala
пакете, поэтому вы можете использовать их указывая обычное имя без необходимости импорта пакета. Примером может служить тип List
, к которому можно получить доступ следующим образом:
scala.collection.immutable.List // Полное объявление
scala.List // объявление через псевдоним
List // т.к. scala._ всегда автоматически импортируется
// можно просто указать имя коллекции
Другие псевдонимы для типов Iterable, Seq, IndexedSeq, Iterator, LazyList, Vector, StringBuilder, и Range.
На следующем рисунке показаны все коллекции из пакета scala.collection
. Это все абстрактные классы или трейты, у которых обычно есть, как изменяемая, так и неизменяемая реализация.
На следующем рисунке показаны все коллекции из пакета scala.collection.immutable
.
И на конец все коллекции из пакета scala.collection.mutable
.
Описания:
Обзор API коллекций
Наиболее важные классы коллекций представлены на рисунках выше. Существует довольно много общего между всеми этими классами. Например, любая коллекция может быть создана по одному общему синтаксису, написав имя класса коллекции, а затем ее элементы:
Iterable("x", "y", "z")
Map("x" -> 24, "y" -> 25, "z" -> 26)
Set(Color.red, Color.green, Color.blue)
SortedSet("hello", "world")
Buffer(x, y, z)
IndexedSeq(1.0, 2.0)
LinearSeq(a, b, c)
Этот же принцип применяется и к конкретным реализациям коллекций, таким как
List(1, 2, 3)
HashMap("x" -> 24, "y" -> 25, "z" -> 26)
Все эти коллекции выводятся с помощью toString
.
Все коллекции поддерживают API, предоставляемый Iterable
, но с определенной спецификой на разных типах, где это имеет смысл. Например, метод map
в классе Iterable
возвращает в результате другой Iterable
. Но в подклассах тип результата переопределяется. Например, вызов map
в List
снова дает List
, вызов наSet
снова дает Set
и так далее.
scala> List(1, 2, 3) map (_ + 1)
res0: List[Int] = List(2, 3, 4)
scala> Set(1, 2, 3) map (_ * 2)
res0: Set[Int] = Set(2, 4, 6)
Такое поведение, повсеместно реализованное для коллекций, называется принцип единообразного типа возвращаемого значения (uniform return type principles).
Большинство классов в иерархии коллекций существуют в трех вариантах: базовый, изменяемый и неизменяемый. Единственным исключением является трейт Buffer
, который существует только в виде изменяемой коллекции.
Далее мы рассмотрим все эти классы поподробнее.
Contributors to this page:
Contents
- Введение
- Изменяемые и Неизменяемые Коллекции
- Трейт Iterable
- Последовательности. Трейт Seq, IndexedSeq и LinearSeq
- Множества
- Мапы
- Реализации Неизменяемых Коллекций
- Реализации Изменяемых Коллекций
- Массивы
- Строки
- Показатели производительности
- Равенство
- Отображения
- Итераторы
- Создание коллекций с нуля
- Преобразования между Java и Scala коллекциями