All you need to know about Collections In Scala

Reading Time: 4 minutes

Introduction

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).

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.

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.

Scala Collection Hierarchy Overview

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.

Commonly Used Collections In Scala

Lists

Scala Lists are quite similar to arrays which means, all the elements of a list have the same type but there are two important differences. First, lists are immutable, which means elements of a list cannot be changed by assignment. Second, lists represent a linked list whereas arrays are flat.

The type of a list that has elements of type T is written as List[T].

We can, for example, declare a list of integers:

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

There are three basic operations on lists:

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

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) // false

Set

Scala Set is a collection of pairwise different elements of the same type. In other words, a Set is a collection that contains no duplicate elements. There are two kinds of Sets, the immutable and the mutable. The difference between mutable and immutable objects is that when an object is immutable, the object itself can’t be changed.

By default, Scala uses the immutable Set. If you want to use the mutable Set, you’ll have to import scala.collection.mutable.Set class explicitly. If you want to use both mutable and immutable sets in the same collection, then you can continue to refer to the immutable Set as Set but you can refer to the mutable Set as mutable.Set.

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 // false

Maps

Scala map is a collection of key/value pairs. Any value can be retrieved based on its key. Keys are unique in the Map, but values need not be unique. Maps are also called Hash tables. There are two kinds of Maps, the immutable and the mutable. The difference between mutable and immutable objects is that when an object is immutable, the object itself can’t be changed.

By default, Scala uses the immutable Map. If you want to use the mutable Map, you’ll have to import scala.collection.mutable.Map class explicitly. If you want to use both mutable and immutable Maps in the same, then you can continue to refer to the immutable Map as Map but you can refer to the mutable set as mutable.Map.

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

So, let’s try them out:

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 // false

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

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

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) // None

Tuples

Scala tuple combines a fixed number of items together so that they can be passed around as a whole. Unlike an array or list, a tuple can hold objects with different types but they are also immutable.

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")

The declaration t1 is just syntactic sugar for a Tuple:

val t1 = Tuple2(1, "A")

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 // A

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 // A

We can iterate over a Tuple using the productIterator method:

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

The output in this case will be:

1
2
3
4

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

Conclusion

In this blog we talked about Collections In scala. We studied about the differences between mutable and immutable collections and explored the commonly used collections in Scala. We also studied about the most commonly used collections in Scala.

References

Written by 

My name is Harshal Dubey. I am working as a Software Intern in Scala Studio at Knoldus. My hobbies are playing volleyball, football and Travelling.