The Scala Collections framework, according to its authors, is designed to be easy to use, concise, safe, fast, and universal.
The framework is made up of Scala traits that are designed to be building blocks for creating collections. For more information on these building blocks, read the official Scala collections overview.
These built-in collections are separated into the immutable and mutable packages. By default, the immutable versions are used. Constructing a List()
(without importing anything) will construct an immutable list.
One of the most powerful features of the framework is the consistent and easy-to-use interface across like-minded collections. For example, summing all elements in a collection is the same for Lists, Sets, Vectors, Seqs and Arrays:
val numList = List[Int](1, 2, 3, 4, 5)
numList.reduce((n1, n2) => n1 + n2) // 15
val numSet = Set[Int](1, 2, 3, 4, 5)
numSet.reduce((n1, n2) => n1 + n2) // 15
val numArray = Array[Int](1, 2, 3, 4, 5)
numArray.reduce((n1, n2) => n1 + n2) // 15
These like-minded types inherit from the Traversable
trait.
It is now a best-practice to use
Vector
instead ofList
because the implementations have better performance Performance characteristics can be found here.Vector
can be used whereverList
is used.
Collection classes that have the Traversable
trait implement foreach
and inherit many methods for performing common operations to collections, which all function identically. The most common operations are listed here:
map
, flatMap
, and collect
produce new collections by applying a function to each element in the original collection.List(1, 2, 3).map(num => num * 2) // double every number = List(2, 4, 6)
// split list of letters into individual strings and put them into the same list
List("a b c", "d e").flatMap(letters => letters.split(" ")) // = List("a", "b", "c", "d", "e")
toList
, toArray
, and many other conversion operations change the current collection into a more specific kind of collection. These are usually methods prepended with 'to' and the more specific type (i.e. 'toList' converts to a List
).val array: Array[Int] = List[Int](1, 2, 3).toArray // convert list of ints to array of ints
isEmpty
, nonEmpty
, size
, and hasDefiniteSize
are all metadata about the set. This allows conditional operations on the collection, or for code to determine the size of the collection, including whether it's infinite or discrete.List().isEmpty // true
List(1).nonEmpty // true
head
, last
, find
, and their Option
variants are used to retrieve the first or last element, or find a specific element in the collection.val list = List(1, 2, 3)
list.head // = 1
list.last // = 3
filter
, tail
, slice
, drop
, and other operations allow for choosing parts of the collection to operate on further.List(-2, -1, 0, 1, 2).filter(num => num > 0) // = List(1, 2)
partition
, splitAt
, span
, and groupBy
split the current collection into different parts.// split numbers into < 0 and >= 0
List(-2, -1, 0, 1, 2).partition(num => num < 0) // = (List(-2, -1), List(0, 1, 2))
exists
, forall
, and count
are operations used to check this collection to see if it satisfies a predicate.List(1, 2, 3, 4).forall(num => num > 0) // = true, all numbers are positive
List(-3, -2, -1, 1).forall(num => num < 0) // = false, not all numbers are negative
foldLeft
(/:
), foldRight
(:\
), reduceLeft
, and reduceRight
are used to apply binary functions to successive elements in the collection. Go here for fold examples and go here for reduce examples.