Skip to content

Scala Collections

Scala offers a rich, powerful, and comprehensive collections library, distinguishing between mutable and immutable collections. Immutable collections, which cannot be changed after creation, are preferred in functional programming as they enhance predictability and safety in concurrent environments.

The base trait for all collections is Iterable[T]. Collections are broadly categorized and reside in packages like scala.collection, scala.collection.immutable, and scala.collection.mutable.

When you write List, Map, Set without an explicit import from mutable, you get the immutable version.

An immutable linked list. Efficient for adding/removing elements at the head (:: operator) and pattern matching. Less efficient for random access by index.

val numbers: List[Int] = List(1, 2, 3, 4)
val names = List("Alice", "Bob")
val emptyList = List.empty[Double]
val listWithPrepended = 0 :: numbers // Result: List(0, 1, 2, 3, 4)

An immutable indexed sequence. Provides efficient random access and updates (effectively constant time). Often a good default choice for an immutable sequence when performance characteristics differ from List.

val numsVec = Vector(10, 20, 30)
val updatedVec = numsVec.updated(1, 25) // Result: Vector(10, 25, 30) (New vector)
val appendedVec = numsVec :+ 40 // Result: Vector(10, 20, 30, 40)

An immutable collection of key-value pairs. Keys are unique.

val colors = Map("red" -> "#FF0000", "green" -> "#00FF00", "blue" -> "#0000FF")
val maybeGreen = colors.get("green") // Returns Option[String]: Some("#00FF00")
val maybeYellow = colors.get("yellow") // Returns Option[String]: None
val addedColor = colors + ("yellow" -> "#FFFF00") // New map with yellow added
val removedColor = colors - "red" // New map without red

An immutable collection of unique elements.

val primes = Set(2, 3, 5, 7, 11)
val hasFive = primes.contains(5) // true
val addedPrime = primes + 13 // New set with 13
val removedPrime = primes - 7 // New set without 7
val unionSet = primes ++ Set(13, 17) // Set(2, 3, 5, 7, 11, 13, 17)

A base trait for sequences (ordered collections). List and Vector are subtypes. Useful when you want to accept any kind of sequence.

def processSequence(seq: Seq[Int]): Int = seq.sum
processSequence(List(1, 2, 3)) // 6
processSequence(Vector(4, 5, 6)) // 15

Found in the scala.collection.mutable package. These collections can be modified in place. Use them when performance benefits of mutation outweigh the advantages of immutability, or when interacting with Java libraries requiring mutable collections.

import scala.collection.mutable
// Mutable List Buffer (efficient for appending)
val listBuffer = mutable.ListBuffer(1, 2)
listBuffer += 3 // Appends 3: ListBuffer(1, 2, 3)
listBuffer.prepend(0) // Prepends 0: ListBuffer(0, 1, 2, 3)
val finalImmutableList = listBuffer.toList // Convert back to immutable List
// Mutable HashMap
val mutableMap = mutable.HashMap("a" -> 1)
mutableMap.put("b", 2) // Add/update in place
mutableMap("a") = 10 // Update in place
// Mutable ArrayBuffer (like Java ArrayList)
val arrayBuffer = mutable.ArrayBuffer("x", "y")
arrayBuffer += "z"
arrayBuffer(0) = "a"

Represents optional values. An instance is either Some[T] (containing a value) or None (representing absence). Crucial for avoiding NullPointerException and handling missing data safely.

val nameOpt: Option[String] = Some("Scala")
val ageOpt: Option[Int] = None
val upperName = nameOpt.map(_.toUpperCase) // Some("SCALA")
val defaultAge = ageOpt.getOrElse(0) // 0

An immutable, fixed-size container holding elements of potentially different types (e.g., Tuple2[Int, String], Tuple3[String, Double, Boolean]). Useful for returning multiple values from a function.

val point: (Int, Int) = (10, 20) // Tuple2[Int, Int]
val personData = ("Alice", 30, true) // Tuple3[String, Int, Boolean]
val x = point._1 // Access first element (1-based index)
val name = personData._1
val (pName, pAge, pActive) = personData // Deconstruction

Not a collection itself, but a way to access elements of a collection sequentially. Iterators are stateful and can typically only be traversed once.

val iterator = List(1, 2, 3).iterator
while (iterator.hasNext) {
println(s"Iterator element: ${iterator.next()}")
}

Scala collections provide a vast array of powerful higher-order functions:

OperationDescription
mapTransforms each element, producing a new collection.
filterSelects elements that satisfy a predicate, producing a new collection.
foreachApplies a procedure (side effect) to each element.
flatMapApplies a function returning a collection to each element, flattening the results.
findReturns the first element satisfying a predicate as an Option.
existsChecks if at least one element satisfies a predicate.
forallChecks if all elements satisfy a predicate.
foldLeft, foldRightCombines elements using a binary operator, starting from left/right.
reduceLeft, reduceRightSimilar to fold, but uses the first/last element as the initial value.
groupByPartitions elements into a Map based on a classifier function.
sorted, sortBySorts elements based on natural or specified ordering.
zip, zipWithIndexCombines elements with another collection or their indices.

Mastering these operations is key to writing concise and expressive Scala code.