I've seen in many examples that sometimes a Seq is being used, while other times is the List...
Is there any difference, other than the former one being a Scala type and the List coming from Java?
I've seen in many examples that sometimes a Seq is being used, while other times is the List...
Is there any difference, other than the former one being a Scala type and the List coming from Java?
In Java terms, Scala's Seq
would be Java's List
, and Scala's List
would be Java's LinkedList
.
Note that Seq
is a trait
, which is similar to Java's interface
, but with the equivalent of up-and-coming defender methods. Scala's List
is an abstract class that is extended by Nil
and ::
, which are the concrete implementations of List
.
So, where Java's List
is an interface
, Scala's List
is an implementation.
Beyond that, Scala's List
is immutable, which is not the case of LinkedList
. In fact, Java has no equivalent to immutable collections (the read only thing only guarantees the new object cannot be changed, but you still can change the old one, and, therefore, the "read only" one).
Scala's List
is highly optimized by compiler and libraries, and it's a fundamental data type in functional programming. However, it has limitations and it's inadequate for parallel programming. These days, Vector
is a better choice than List
, but habit is hard to break.
Seq
is a good generalization for sequences, so if you program to interfaces, you should use that. Note that there are actually three of them: collection.Seq
, collection.mutable.Seq
and collection.immutable.Seq
, and it is the latter one that is the "default" imported into scope.
There's also GenSeq
and ParSeq
. The latter methods run in parallel where possible, while the former is parent to both Seq
and ParSeq
, being a suitable generalization for when there is no concern for code parallelism. They are both relatively new, so people don't use them as much.
UnsupportedOperationException
because of this. To create an immutable list in Java you use the Collections.unmodifiableList() and similarly there are other methods for Sets, Maps etc. docs.oracle.com/javase/6/docs/api/java/util/… –
Counterfeit extends
and the actual concrete class passed is of a sub-type Java makes use of an unmodifiable collection to enforce the receiving method not to modify it, thus avoiding insertion of an object of a different subtype. Yes the case you are mentioning allows you to modify the object contained in the collection, but for the sake of type safety it still holds. –
Counterfeit Seq
is a trait, then why can I instantiate it? e.g., why is var x = Seq(1, 2, 3)
legal? –
Ultra Seq
object inherits an apply
method. –
Lammastide Seq
is both a trait and an object. When you write var x = Seq(1, 2, 3)
, you are calling the apply
method on the object. –
Associative Seq
is not a lazy operation. It's an interface, which List
implements. –
Associative A Seq is an Iterable that has a defined order of elements. Sequences provide a method apply()
for indexing, ranging from 0 up to the length of the sequence. Seq has many subclasses including Queue, Range, List, Stack, and LinkedList.
A List is a Seq that is implemented as an immutable linked list. It's best used in cases with last-in first-out (LIFO) access patterns.
Here is the complete collection class hierarchy from the Scala FAQ:
prepend()
and head()
operations as O(1) vs append()
OR last()
, which is O(n) of number of elements in the list. –
Effectuate Seq
is a trait that List
implements.
If you define your container as Seq
, you can use any container that implements Seq
trait.
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
Note that
scala> val a = Seq(1,2,3)
a: Seq[Int] = List(1, 2, 3)
Is just a short hand for:
scala> val a: Seq[Int] = List(1,2,3)
a: Seq[Int] = List(1, 2, 3)
if the container type is not specified, the underlying data structure defaults to List
.
In Scala, a List inherits from Seq, but implements Product; here is the proper definition of List :
sealed abstract class List[+A] extends AbstractSeq[A] with Product with ...
[Note: the actual definition is a tad bit more complex, in order to fit in with and make use of Scala's very powerful collection framework.]
As @daniel-c-sobral said, List extends the trait Seq and is an abstract class implemented by scala.collection.immutable.$colon$colon
(or ::
for short), but technicalities aside, mind that most of lists and seqs we use are initialized in the form of Seq(1, 2, 3)
or List(1, 2, 3)
which both return scala.collection.immutable.$colon$colon
, hence one can write:
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]]
As a result, I'd argue than the only thing that matters are the methods you want to expose, for instance to prepend you can use ::
from List that I find redundant with +:
from Seq and I personally stick to Seq by default.
© 2022 - 2024 — McMap. All rights reserved.
String
is not a collection, it is an example of immutable classes familiar to Java programmers. – Tahr