Vector
In Scala 3.3 a vector is an immutable collection. But it can be added to, and updated, fast. It is represented with a tree of nodes.
Unlike an array, a vector's elements cannot be reassigned. But with update()
we can change elements in a vector, copying only the nodes needed.
Let us gain familiarity with Scala vector syntax. We use a ":+" operator to add a value to the end of a vector. We start with Vector.empty
.
println
to display the contents of a vector. A for
-loop can be used to access and print all individual elements.object Program { def main(args: Array[String]): Unit = { // Begin with an empty vector. val vector = scala.collection.immutable.Vector.empty println(vector) // Add new value at end of vector. val vector2 = vector :+ 5 println(vector2) // Add 2 new values at end of vector. val vector3 = vector2 :+ 10 :+ 20 println(vector3) // Add new value at start of vector. val vector4 = 100 +: vector3 println(vector4) } }Vector() Vector(5) Vector(5, 10, 20) Vector(100, 5, 10, 20)
List
Sometimes we want to add an entire List
to a Vector
. We want to place all the elements from the List
into a vector in one operation. The "++" operator helps here.
object Program { def main(args: Array[String]): Unit = { val v = scala.collection.immutable.Vector.empty println(v) // Add elements from List of Ints to end of vector. val v2 = v ++ List(10, 20, 30) println(v2) } }Vector() Vector(10, 20, 30)
Here we update a string
vector. We add 3 strings (cat, bird and frog) to the end of an empty vector. And then we update the element at index 1 to equal "fish."
val
keyword. When we call update, only some parts of v2 are updated and copied.object Program { def main(args: Array[String]): Unit = { val v = scala.collection.immutable.Vector.empty println(v) // Add 3 strings to an empty vector. val v2 = v :+ "cat" :+ "bird" :+ "frog" println(v2) // Update element at index 1. val changed = v2.updated(1, "fish") println(changed) } }Vector() Vector(cat, bird, frog) Vector(cat, fish, frog)
For
-loopLooping over a collection is essential. Here we use a for
-loop to enumerate the elements in a vector. We encounter all 3 Int
values and print them.
object Program { def main(args: Array[String]): Unit = { // Create an Int vector. // ... Append 3 elements. val v = scala.collection.immutable.Vector.empty :+ 5 :+ 10 :+ 50 println(v) // Loop over the vector's elements. for (e <- v) { println(e) } } }Vector(5, 10, 50) 5 10 50
Vector
benchmarkThe performance of a Vector
is complicated to measure. In recent versions of Scala (as of 2023), the Vector
is competitive to the List
.
List
instead of a vector.List
in this benchmark.object Program { def main(args: Array[String]): Unit = { // Warm up the JIT. val testVector = scala.collection.immutable.Vector.empty :+5 :+ 10 val testVector2 = 100 +: testVector val testList = List(5, 10) val testList2 = 100 :: testList val t1 = System.currentTimeMillis() // Version 1: add three elements to a vector. for (i <- 0 to 1000000) { val vector = scala.collection.immutable.Vector.empty :+5 :+ 10 val vector2 = 100 +: vector if (vector2.length != 3) { println(vector2.length) } } val t2 = System.currentTimeMillis() // Version 2: add three elements to a list. for (i <- 0 to 1000000) { val list = List(5, 10) val list2 = 100 :: list if (list2.length != 3) { println(list2.length) } } val t3 = System.currentTimeMillis() // Results. println(t2 - t1) println(t3 - t2) } }28 ms, Vector 37 ms, List
They are an advanced collection, and in some sense they are an efficient, immutable array. For large collections of Ints or similar values, they are a good choice.
Scala includes collections. These introduce a considerable amount of flexibility. A vector fills a requirement for an immutable, easily-updated array with fast element access.