The Scala collections library is a rich toolkit, and it takes some time to get used to all it offers. One of those choices are Scala Vectors – let’s examine why it might be good one.
When I first started working with Scala, back in 2.7 days I believe, Vector wasn’t there, but it was introduced in 2.8, and quickly became one of my favorites in the colection library. It has some efficiency advantages over Lists, that we’ll explore later, and is, like a list, an immutable sequential collection with all the methods you’d expect on List and a few more.
- Captain Oveur
You can create a Vector just like a List, like so:
scala> val victor = Vector(3, 2, 1) victor: scala.collection.immutable.Vector[Int] = Vector(3, 2, 1)
Unlike a list, though, a Vector is indexed, so we can say:
scala> victor(2) res1: Int = 1
If we wanted an index on a list we’d have to use zipWithIndex to generate it, or turn it into another type (like a Vector!)
You can perform the usual immutable operations, such as returning a vector with new elements appended, such as
scala> val crew = Vector("roger", "over") :+ "victor" crew: scala.collection.immutable.Vector[String] = Vector(roger, over, victor)
You can also replace one element by index easily:
scala> val second = crew.updated(1, "joe") second: scala.collection.immutable.Vector[String] = Vector(roger, joe, victor)
Which would be a bit trickier with a list.
Vector also has the advantage of generally being faster and more efficient with RAM than a plain List. If you use a Seq, you’ve probably already used a Vector – it’s the default implementation of a Seq.
The Vector is also slightly more abstract than List, in the sense that we are saying we have a collection with a specific order and a finite length, I’m not ensuring that I can only do full traversals (such as with a list).
There’s the usual huge list of operations available on Vector, even more than on list. If we ask the REPL (by hitting “tab” after the dot):
scala> victor. ++ ++: +: /: /: :+ : addString aggregate andThen apply applyOrElse asInstanceOf canEqual collect collectFirst combinations companion compose contains containsSlice copyToArray copyToBuffer corresponds count diff distinct drop dropRight dropWhile endsWith exists filter filterNot find flatMap flatten fold foldLeft foldRight forall foreach genericBuilder groupBy grouped hasDefiniteSize head headOption indexOf indexOfSlice indexWhere indices init inits intersect isDefinedAt isEmpty isInstanceOf isTraversableAgain iterator last lastIndexOf lastIndexOfSlice lastIndexWhere lastOption length lengthCompare lift map max maxBy min minBy mkString nonEmpty orElse padTo par partition patch permutations prefixLength product reduce reduceLeft reduceLeftOption reduceOption reduceRight reduceRightOption repr reverse reverseIterator reverseMap runWith sameElements scan scanLeft scanRight segmentLength seq size slice sliding sortBy sortWith sorted span splitAt startsWith stringPrefix sum tail tails take takeRight takeWhile to toArray toBuffer toIndexedSeq toIterable toIterator toList toMap toSeq toSet toStream toString toTraversable toVector transpose union unzip unzip3 updated view withFilter zip zipAll zipWithIndex
So, the next time you reach for a collection, consider the humble Vector, it may just be on the course you need!