Scala - Collections
Range
: immutable,IndexedSeq
List
: immutable,LinearSeq
LinkedList
: mutable,LinearSeq
Array
: mutable,IndexedSeq
Vector
: immutable,IndexedSeq
Comparisons
IndexedSeq vs LinearSeq
- IndexedSeq: efficient for random access
- LinearSeq: efficient for add/delete head/tail
Tuple vs List
-
Tuple: elements may have different types
-
List: same type
-
Tuple: cannot iterate
-
List: can iterate
-
Tuple: 1-based index
-
List: 0-based index
Tuple means a product between all of its elements, but a non-empty List is a product between its head and tail.
scala> List(1,2).productIterator.foreach(println)
1
List(2)
scala> Tuple2(1,2).productIterator.foreach(println)
1
2
Range vs List vs Array vs Vector vs ...
scala> (1 to 5).toList
res4: List[Int] = List(1, 2, 3, 4, 5)
scala> (1 to 5).toVector
res5: Vector[Int] = Vector(1, 2, 3, 4, 5)
scala> (1 to 5).toArray
res68: Array[Int] = Array(1, 2, 3, 4, 5)
scala> List.range(1,6)
res1: List[Int] = List(1, 2, 3, 4, 5)
immutable: always return a copy with changes
scala> val x = (1 to 5).toVector
x: Vector[Int] = Vector(1, 2, 3, 4, 5)
change a value in vector(the function is called updated
, not update
)
scala> x.updated(0, 100)
res13: scala.collection.immutable.Vector[Int] = Vector(100, 2, 3, 4, 5)
For a full list: https://docs.scala-lang.org/tutorials/FAQ/collections.html
Seq
3 Seq
: collection.Seq
, collection.mutable.Seq
and collection.immutable.Seq
, The immutable one is the "default".
ParSeq
: parallelGenSeq
: parent toSeq
andParSeq
List
List
is highly optimized by compiler and libraries, and it's a fundamental data type in functional programming.
scala> List("a", "b", "c").zipWithIndex
res0: List[(String, Int)] = List((a,0), (b,1), (c,2))
scala> List("a", "b", "c") zip (Stream from 1)
res1: List[(String, Int)] = List((a,1), (b,2), (c,3))
scala> (List("a", "b", "c") zip (Stream from 1)).map({case (x,y)=>(y,x)})
res2: List[(Int, String)] = List((1,a), (2,b), (3,c))
Create repeated elements
scala> Seq.fill(5)("a")
res1: Seq[String] = List(a, a, a, a, a)
Vector
A hybrid of List
and Array
.
Tuple
There's no Entry
object as in Java, instead Scala uses Tuple2
scala> val t1 = 1 -> 2
t1: (Int, Int) = (1,2)
scala> val t2 = Tuple2(1,2)
t2: (Int, Int) = (1,2)
scala> t1 == t2
res1: Boolean = true
Since t1
and t2
are the same, you will only find one in the created Map; for the same key, the latter will override the existing value:
scala> Map(t1, t2, 3->4)
res12: scala.collection.immutable.Map[Int,Int] = Map(1 -> 2, 3 -> 4)
scala> Map(t1, t2, 3->4, 3->5)
res13: scala.collection.immutable.Map[Int,Int] = Map(1 -> 2, 3 -> 5)
scala> val info = (5, "abc", true)
info: (Int, String, Boolean) = (5,abc,true)
scala> val name = info._2
name: String = abc
create 2-sized tuple
scala> 1 -> 2
res13: (Int, Int) = (1,2)
Map
Mutable map
3 ways
scala> val map = scala.collection.mutable.Map[String,String]()
map: scala.collection.mutable.Map[String,String] = Map()
scala> map("k1") = "v1"
scala> map
res1: scala.collection.mutable.Map[String,String] = Map((k1,v1))
scala> map += "k2" -> "v2"
res2: map.type = Map((k1,v1), (k2,v2))
scala> map.put("k3","v3")
res3: Option[String] = None
scala> map
res4: scala.collection.mutable.Map[String,String] = Map((k3,v3), (k1,v1), (k2,v2))
Immutable map
var map
scala> var map = scala.collection.immutable.Map[String, String]()
map: scala.collection.immutable.Map[String,String] = Map()
scala> map += ("key4" -> "val4")
scala> map
res1: scala.collection.immutable.Map[String,String] = Map(key4 -> val4)
val map
Create a new map.
scala> val map = scala.collection.immutable.Map[String, String]()
map: scala.collection.immutable.Map[String,String] = Map()
scala> val map2 = map + ("key4" -> "val4")
map2: scala.collection.immutable.Map[String,String] = Map(key4 -> val4)
Range:
Create a Range
by to
scala> 1 to 5
res1: scala.collection.immutable.Range.Inclusive = Range(1, 2, 3, 4, 5)
Or use until
scala> 1 until 6
res47: scala.collection.immutable.Range = Range(1, 2, 3, 4, 5)
set step
scala> 1 to 5 by 2
res48: scala.collection.immutable.Range = Range(1, 3, 5)
NumericRange:
scala> val x = 1.0 to 5.0
x: Range.Partial[Double,scala.collection.immutable.NumericRange[Double]] = scala.collection.immutable.Range$Partial@29ad44e3
scala> val y = x by 0.5
y: scala.collection.immutable.NumericRange[Double] = NumericRange(1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0)
Inclusive vs Exclusive
until
scala> val y = 1 until 6
y: scala.collection.immutable.Range = Range(1, 2, 3, 4, 5)
scala> x.start
res8: Int = 1
scala> x.end
res9: Int = 5
scala> x.isInclusive
res11: Boolean = true
scala> y.start
res12: Int = 1
scala> y.end
res13: Int = 6
scala> y.isInclusive
res14: Boolean = false
Sequence Comprehension
scala> for (x <- 1 to 5) { println(x) }
1
2
3
4
5
scala> for (x <- 1 to 5 if x % 2 == 0) { println(x) }
2
4
Array to lookup map
scala> val a = Array("hello", "world", "foo", "bar")
a: Array[String] = Array(hello, world, foo, bar)
scala> val lookup = a.map(word => word -> word.length).toMap
lookup: scala.collection.immutable.Map[String,Int] = Map(hello -> 5, world -> 5, foo -> 3, bar -> 3)
scala> lookup("world")
res3: Int = 5