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


299

Я бачив у багатьох прикладах, що інколи використовується Seq, а інший раз - це Список ...

Чи є якась різниця, окрім колишнього типу Scala та Список, що походить від Java?

Відповіді:


408

З точки зору Java, Scala Seqбуде Java List, а Scala - ListJava LinkedList.

Зауважте, що Seqце а trait, що еквівалентно Java interface, але з еквівалентом сучасних методів захисту. Scala's List- це абстрактний клас, який поширюється на, Nilі ::які є конкретними реалізаціями List.

Отже, там, де Java Listє interface, Scala List- це реалізація.

Крім того, Скала Listнезмінна, що не стосується LinkedList. Насправді, Java не має еквівалента незмінних колекцій (лише те, що читає, гарантує лише те, що новий об’єкт неможливо змінити, але ви все одно можете змінити старий, а отже, і "лише для читання").

Скала Listоптимізована компілятором та бібліотеками, і це фундаментальний тип даних у функціональному програмуванні. Однак у нього є обмеження і він недостатній для паралельного програмування. У наші дні Vectorце кращий вибір ніж List, але звичку важко зламати.

Seqє хорошим узагальненням для послідовностей, тому, якщо ви програмуєте інтерфейси, ви повинні використовувати це. Зверніть увагу , що є на насправді три з них: collection.Seq, collection.mutable.Seqі collection.immutable.Seq, і це той один , який є « по умовчанням» імпортований в область видимості.

Там також GenSeqі ParSeq. Останні методи виконуються паралельно, де це можливо, тоді як перший є батьківським для обох Seqі ParSeqє підходящим узагальненням, коли паралелізм коду не має значення. Вони обидві відносно нещодавно представлені, тому люди ще не дуже їх використовують.


3
RE "Java не має еквівалента незмінних колекцій" , хоча Stringце не колекція, але це приклад незмінних класів, знайомих Java-програмістам.
huynhjl

15
@huynhjl Це зовсім не до речі. Я проводив паралелі між тим, що існує в Яві, і тим, що існує в 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 є багато підкласів, включаючи чергу, діапазон, список, стек та 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.


18

У Scala список успадковується від Seq, але реалізує продукт ; ось правильне визначення Списку :

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

[Примітка: фактичне визначення . Це трохи трохи складніше, для того , щоб вписатися в і використовувати дуже потужні рамки колекції в Scala]


0

Як сказав @ daniel-c-sobral, List розширює ознаку Seq і є абстрактним класом, реалізованим scala.collection.immutable.$colon$colon(або ::коротко), але технічні характеристики, окрім того, що більшість списків і послідовностей, які ми використовуємо, ініціалізуються у вигляді 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 за замовчуванням.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.