Scala – Collections | Mutable Collections | Immutable Collections

If You are interested to learn about the scala Array

Scala has a rich set of collection library. Collections are containers of things. Those containers can be sequenced, linear sets of items like List, Tuple, Option, Map, etc. The collections may have an arbitrary number of elements or be bounded to zero or one element (e.g., Option).

Collections may be strict or lazy. Lazy collections have elements that may not consume memory until they are accessed, like Ranges. Additionally, collections may be mutable (the contents of the reference can change) or immutable (the thing that a reference refers to is never changed). Note that immutable collections may contain mutable items.

For some problems, mutable collections work better, and for others, immutable collections work better. When in doubt, it is better to start with an immutable collection and change it later if you need mutable ones.

This chapter throws light on the most commonly used collection types and most frequently used operations over those collections.

Sr.NoCollections with Description
1Scala ListsScala’s List[T] is a linked list of type T.
2Scala SetsA set is a collection of pairwise different elements of the same type.
3Scala MapsA Map is a collection of key/value pairs. Any value can be retrieved based on its key.
4Scala TuplesUnlike an array or list, a tuple can hold objects with different types.
5Scala OptionsOption[T] provides a container for zero or one element of a given type.
6Scala IteratorsAn iterator is not a collection, but rather a way to access the elements of a collection one by one.

Types of Scala Collections

There are two types of collections in Scala – mutable and immutable. Let’s point out some differences.

Mutable Collections

A mutable collection updates or extends in place. This means we can add, change or remove elements of a collection as a side effect. These collections have operations that change the collection in place. All mutable collection classes are present in the scala.collection.mutable package.

Immutable Collections

All immutable collections are present under scala.collection.immutable. We can perform operations such as additions, removals, or updates, but these operations always return a new collection and leave the old collection unchanged.

Scala Collection Hierarchy Overview

Screenshot-2020-05-07

Scala’s collection classes begin with the Traversable and Iterable traits. These traits branch into three main categories: ListSet, and Map.

The Traversable trait allows us to traverse an entire collection. It’s a base trait for all other collections. It implements the common behavior in terms of a foreach method.

The Iterable trait is the next trait from the top of the hierarchy and a base trait for iterable collections. It defines an iterator which allows us to loop through a collection’s elements one at a time. When we use an iterator, we can traverse the collection only once. This is mainly because each element gets processed during the iteration process.

Now, let’s explore some of the most common immutable collections of the Scala library.

Most Commonly Used Scala Collections

List

Scala lists internally represent an immutable linked list. It maintains the order of elements and can contain duplicates as well. This class is optimal for last-in-first-out (LIFO), stack-like access patterns.

It also implements structural sharing of the tail list. This means that many operations have either a constant memory footprint or no memory footprint at all.

A list has O(1) prepend and head/tail access. Most other operations are O(n) though; this includes length, append, reverse, and also the index-based lookup of elements. We can, for example, declare a list of integers:

val numbersList: List[Int] = List(1, 2, 3 ,4)
val emptyList: List[Int] = List() // Empty ListCopy

This List class comes with two implementing case classes, scala.Nil and scala.::, that implement the abstract members isEmptyhead, and tail. A Scala list containing elements can be represented using x :: xs, where x is the head and the xs is the remaining list. Nil represents an empty list:

val numbersList: List[Int] = 1 :: 2 :: 3 :: 4 :: Nil  // List of Integers
val emptyList: List[Int] = Nil  // Empty List
val x :: xs = numbersList
assert(x == 1) // true
assert(xs == List(2, 3, 4)) // trueCopy

In the above example, we can represent the numbersList using the x :: xs notation. While printing the value of x and xs, we find that x is the head of the list, and xs is the remaining list.

There are three basic operations on lists:

No.MethodDescription
1headReturns the first element of the List
2tailReturns a List consisting of all elements except head (the first element)
3isEmptyReturns true if the List is empty

Let’s try using each one in turn:

val numbersList: List[Int] = 1 :: 2 :: 3 :: 4 :: Nil
assert(numbersList.head == 1) // true
assert(numbersList.tail == List(2, 3, 4)) // true
assert(numbersList.isEmpty) // falseCopy

Other common operations include concatenating two lists, creating uniform lists, and reversing a list:

List(1,2) ::: List(3,4) // List(1, 2, 3, 4)

List.fill(3)(100) // List(100, 100, 100)

List(1,2,3,4).reverse // List(4, 3, 2, 1)Copy

We can find the complete list of Scala List methods in the ScalaDoc.

Set

Scala Set is a collection of unique elements. By default, Scala uses an immutable set. It doesn’t maintain any order for storing elements.

We can declare an immutable set as:

val emptySet: Set[Int] = Set() // Empty set
val numbersSet: Set[Int] = Set(1, 2, 3, 4) // Set of integersCopy

If we want to use a mutable Set, we need to import it from the collection.mutable explicitly:

val mutableSet = collection.mutable.Set(1, 2, 3)Copy

The operations on a Set are similar to the ones on the List:

No.MethodDescription
1headReturns the first element of a Set
2tailReturns a Set consisting of all elements except head (the first element)
3isEmptyReturns true if the Set is empty

So, let’s try them out:

Set(1, 2, 3, 4).head // 1
Set(1, 2, 3, 4).tail // Set(2, 3, 4)
Set(1, 2, 3, 4).isEmpty // falseCopy

The complete list of methods of Scala Set is in the ScalaDoc.

Map

Map is a collection of key/value pairs where keys are always unique. Scala provides mutable and immutable versions of it. By default, an immutable version of the map is imported:

val immutableMap = Map(1 -> "a", 2 -> "b")Copy
val mutableMap = collection.mutable.Map(1 -> "a", 2 -> "b")Copy

The methods for working with maps are bit different:

No.MethodDescription
1keysReturns an iterable containing all keys of the Map
2valuesReturns an iterable containing all values of the Map
3isEmptyReturns true if the Map is empty

Let’s see how these methods work:

Map(1 -> "a", 2 -> "b").keys // res0: Iterable[Int] = Set(1, 2)

Map(1 -> "a", 2 -> "b").values // res1: Iterable[String] = Iterable(a, b)

Map(1 -> "a", 2 -> "b").isEmpty // falseCopy

The get method returns an optional value. Its signature in the Map trait is as follows:

def get(key: K): Option[V]Copy

When the key exists, it returns the value in Some context, whereas if the key does not exist, it returns None:

Map(1 -> "a", 2 -> "b").get(1) // Some(a)

Map(1 -> "a", 2 -> "b").get(3) // NoneCopy

We can find the complete list of methods of Scala Map in the ScalaDoc.

Tuple

Tuple is a collection that gives us a way to store different items in the same container. It combines a fixed number of items. We can pass this as a whole, and there’s no need to declare a class separately.

Scala 2.x has classes named Tuple2Tuple3 … up to Tuple22.

If we just place some elements inside parentheses, we get a Tuple. A tuple of int and String would look like:

val t1 = (1, "A")Copy

The declaration t1 is just syntactic sugar for a Tuple:

val t1 = Tuple2(1, "A")Copy

There are two ways to access a tuple’s elements. The first way is to access them by the element number:

val tuple3 = (1, "One", "A") // tuple3: (Int, String, String)
tuple3._1 // 1
tuple3._2 // One
tuple3._3 // ACopy

The second way of accessing elements is by using the classical pattern matching in Scala. In this way, we can assign the Tuple elements to some appropriate variable names:

val (num, word, char)  = (1, "One", 'A')
num // 1
word // One
char // ACopy

We can iterate over a Tuple using the productIterator method:

val tuple = (1,2,3,4)
tuple.productIterator.foreach(println)Copy

which would, in this case, output:

1
2
3
4Copy

Technically, Scala 2.x tuples are not collections classes and hence they do not extend the Iterable trait.

Conclusion

In this tutorial, we explored the Scala’s collection library. We looked at the differences between mutable and immutable collections and explored the commonly used collections in Scala.

Scala – Collections | Mutable Collections | Immutable Collections
Show Buttons
Hide Buttons