Разница между последовательностью и списком в Scala

299

Я видел во многих примерах, что иногда используется Seq, а в других случаях это список ...

Есть ли какая-то разница, кроме того, что предыдущий является типом Scala и List поступает с Java?

opensas
источник

Ответы:

408

С точки зрения Java, Scala Seqбудет Java List, а Scala Listбудет Java LinkedList.

Обратите внимание, что Seqэто trait, что эквивалентно Java interface, но с эквивалентом новых методов защиты. Scala List- это абстрактный класс, который расширяется на Nilи и ::который является конкретной реализацией List.

Итак, где Java List- это interfaceScala List- это реализация.

Помимо этого, Scala's Listявляется неизменным, что не так LinkedList. Фактически, Java не имеет эквивалента неизменным коллекциям (только для чтения гарантирует, что новый объект не может быть изменен, но вы все равно можете изменить старый и, следовательно, «только для чтения»).

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

Seqявляется хорошим обобщением для последовательностей, поэтому, если вы программируете на интерфейсы, вы должны использовать это. Обратите внимание , что есть на самом деле три из них: collection.Seq, collection.mutable.Seqи collection.immutable.Seq, и это тот один , который является « по умолчанию» импортирован в область видимости.

Там же GenSeqи ParSeq. Последние методы работают параллельно, где это возможно, в то время как первый является родительским для обоих Seqи ParSeqявляется подходящим обобщением для случаев, когда параллелизм кода не имеет значения. Они оба относительно недавно введены, поэтому люди еще не пользуются ими.

Даниэль С. Собрал
источник
3
RE «Java не имеет эквивалента неизменным коллекциям» , хотя Stringэто и не коллекция, это пример неизменяемых классов, знакомых программистам на Java.
huynhjl
15
@huynhjl Это не относится к делу. Я проводил параллели между тем, что существует в Java, и тем, что существует в Scala, и в Java просто нет концепции изменчивых / неизменных коллекций.
Даниэль С. Собрал
2
У Java фактически есть эквивалент неизменных коллекций. Это не то, что «хорошо рекламируется», а там, и когда вы интенсивно используете дженерики, вы, вероятно, поразите некоторых UnsupportedOperationExceptionиз-за этого. Для создания неизменяемого списка в Java вы используете Collections.unmodifiableList () и аналогичным образом есть другие методы для Наборов, Карт и т. Д. Docs.oracle.com/javase/6/docs/api/java/util/…
jbx
27
@jbx Не правда. Если вы используете эти методы, вы получите объект, который будет вызывать исключения в методах, которые его модифицируют, но не неизменный объект. Если исходный объект модифицируется после того, как немодифицируемый объект был создан, немодифицируемый объект будет отражать это. Итак, неизменяемый, да, неизменный, нет.
Даниэль С. Собрал
3
@jbx Получающий метод не может хранить ссылку на полученную коллекцию и полагать, что она никогда не изменится, и в стандартной библиотеке Java нет типа, который гарантировал бы это - это неизменность. Так, например, этот метод получения не может гарантировать безопасность потока. И это даже не касается постоянных характеристик, обеспечиваемых неизменностью. Без всего этого его нельзя назвать «эквивалентным».
Даниэль С. Собрал,
81

СтартПослед является Iterable , что имеет определенный порядок элементов. Последовательности обеспечивают метод apply()индексации, начиная от 0 до длины последовательности. Seq имеет много подклассов, включая Queue, Range, List, Stack и LinkedList.

Список является Seq , который реализован в виде неизменного связанного списка. Лучше всего его использовать в случаях с шаблонами доступа «последний пришел - первым вышел» (LIFO).

Вот полная иерархия классов коллекции из FAQ по Scala :

введите описание изображения здесь

Цезарь Баутиста
источник
2
Где Array (и ArrayBuffer)? Это не из-за повторяемости
Питер Краусс
23

Seqэто черта, которая Listреализует.

Если вы определите свой контейнер как Seq, вы можете использовать любой контейнер, который реализует Seqчерту.

scala> def sumUp(s: Seq[Int]): Int = { s.sum }
sumUp: (s: Seq[Int])Int

scala> sumUp(List(1,2,3))
res41: Int = 6

scala> sumUp(Vector(1,2,3))
res42: Int = 6

scala> sumUp(Seq(1,2,3))
res44: Int = 6

Обратите внимание, что

scala> val a = Seq(1,2,3)
a: Seq[Int] = List(1, 2, 3)

Это просто короткая рука для:

scala> val a: Seq[Int] = List(1,2,3)
a: Seq[Int] = List(1, 2, 3)

если тип контейнера не указан, базовой структурой данных по умолчанию является List.

Akavall
источник
18

В Scala List наследуется от Seq, но реализует Product ; Вот правильное определение List :

sealed abstract class List[+A] extends AbstractSeq[A] with Product with ...

[Примечание: фактическое определение . Это чуть немного сложнее, для того , чтобы вписаться в и использовать очень мощные рамки коллекции в Scala]

zakelfassi
источник
0

Как сказал @ daniel-c-sobral, List расширяет черту Seq и является абстрактным классом, реализуемым scala.collection.immutable.$colon$colon(или ::для краткости), но, за исключением технических аспектов, помните, что большинство используемых нами списков и seqs инициализируются в форме Seq(1, 2, 3)или List(1, 2, 3)которые оба возвращают scala.collection.immutable.$colon$colonследовательно, можно написать:

var x: scala.collection.immutable.$colon$colon[Int] = null
x = Seq(1, 2, 3).asInstanceOf[scala.collection.immutable.$colon$colon[Int]]
x = List(1, 2, 3).asInstanceOf[scala.collection.immutable.$colon$colon[Int]]

В результате, я бы сказал, что единственное, что имеет значение, - это методы, которые вы хотите раскрыть, например, предисловие, которое вы можете использовать ::из списка, который я считаю избыточным +:из Seq, и я лично придерживаюсь Seq по умолчанию.

профитроль
источник