Scala Language Collections Introduction to Scala Collections


Example

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 of List because the implementations have better performance Performance characteristics can be found here. Vector can be used wherever List is used.

Traversable types

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 - 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")
  • Conversions - 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
  • Size info - 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
  • Element retrieval - 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
List(-2, -1, 0, 1, 2).filter(num => num > 0) // = List(1, 2)
  • Subdivision operations - 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))
  • Element tests - 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