Scala collections in a nutshell
Tags: scala, java, jvm, functional
Published: 2020-09-19 12:38:47

<p>The Scala language, being a mix of object oriented and functional programming paradigms, has a quite unique collection framework, compared to some other languages. Although inheriting a lot from Java and JVM world, the Scala has a much easier and to use API and is overall more polished. </p>

<p>In this post, I will show you a range of Scala collections, how to use them with code samples, and where to use them. Enjoy!</p>

<h2>Scala <code>collection</code> package(s)</h2>

<p>First, let's have a look at the packages that contain all the Scala collections. The top-level package is called as you might expect - <code>collection</code>.  What is more interesting, are the sub-packages included in it. Those contain a more specialized version of typical collections, tailored for the specific use case. </p>

<p>Whether you require parallel processing, concurrent access or just want to have a normal key-based lookup - just import the right package, and you are good to go!</p>

<p>The table below presents the name of <code>collections</code> sub-package, as well as brief description of what you can find there.</p>

<table><thead><tr><th>Package Name</th><th>Description</th></tr></thead><tbody><tr><td><code>collection</code></td><td>Defines the base traits and objects needed to use and extend Scala’s collections<br>library, including all definitions in sub-packages. Most of the abstractions you’ll<br>work with are defined here.</td></tr><tr><td><code>collection.concurrent</code></td><td>Defines a <em>Map </em>trait and <em>TrieMap </em>class with atomic, lock-free access<br>operations.</td></tr><tr><td><code>collection.convert</code></td><td>Defines types for wrapping Scala collections with Java collection abstractions<br>and wrapping Java collections with Scala collection abstractions</td></tr><tr><td><code>collection.generic</code></td><td>Defines reusable components used to build the specific mutable, immutable,<br>etc. collections.</td></tr><tr><td><code>collection.immutable</code></td><td>Defines the immutable collections, the ones you’ll use most frequently.</td></tr><tr><td><code>collection.mutable</code></td><td>Defines mutable collections. Most of the specific collection types are available<br>in mutable and immutable forms, but not all.</td></tr><tr><td><code>collection.parallel</code></td><td>Defines reusable components used to build specific mutable and immutable<br>collections that distribute processing to parallel threads</td></tr><tr><td><code>collection.parallel.immutable</code></td><td>Defines parallel, immutable collections.</td></tr><tr><td><code>collection.parallel.mutable</code></td><td>Defines parallel, mutable collections.</td></tr><tr><td><code>collections.script</code></td><td>A deprecated package of tools for observing collection operations.</td></tr></tbody></table><figcaption>Source: <a href="https://learning.oreilly.com/library/view/programming-scala-2nd/9781491950135/" target="_blank" rel="noreferrer noopener">Programming Scala, 2nd Edition</a></figcaption>

<!-- wp:paragraph -->
<p>As you can see the range of options is very wide. On one hand, it is always good to have an appropriate collection for any use case. On the other hand, it is quite difficult to get started, if you are just looking to implement simple <code>Map</code>.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>For the purpose of this post, let's focus on the most widely used collections - <code>immutable</code> </p>
<!-- /wp:paragraph -->

<!-- wp:heading -->
<h2><code>collection.immutable</code></h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>The package of immutable collections is the most popular out of all Scala collections. In fact, this package is included in the scope by default, so we can start using it without any imports.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>This package includes lots of both traits and concrete implementations of certain data structures. The image below shows those (blue is a <em>trait</em>, and black is <em>class</em>):</p>
<!-- /wp:paragraph -->

<!-- wp:image {"id":3841,"sizeSlug":"large"} -->
<figure class="wp-block-image size-large"><img src="https://bartoszgajda.com/wp-content/uploads/2020/08/collections-immutable-diagram.svg" alt="" class="wp-image-3841"/><figcaption>Source: <a href="https://docs.scala-lang.org/overviews/collections/overview.html" target="_blank" rel="noreferrer noopener">Scala Docs</a></figcaption></figure>
<!-- /wp:image -->

<!-- wp:paragraph -->
<p>Now, let's set that aside and actually learn to use some of the basic collections. The following sections focus on some of the widely used implementations, one at a time.</p>
<!-- /wp:paragraph -->

<!-- wp:heading -->
<h2><code>Set</code></h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>The first one on the list is <code>Set</code>. This is a collection, which contains no duplicate elements. If having only unique elements in the collection, that is the one you should choose. A <code>Set</code> is created like that:</p>
<!-- /wp:paragraph -->

<!-- wp:enlighter/codeblock -->
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">// Set of Char type
val set: Set[Char] = Set('a', 'b', 'c')

// Or just empty Set
val setOfInt: Set[Int] = Set()</pre>
<!-- /wp:enlighter/codeblock -->

<!-- wp:paragraph -->
<p>What's interesting about operations in <code>Set</code>, is the <code>apply</code> method. The <code>apply</code> method behaves like <code>contains</code> method - both check whether the <code>Set</code> contains a given element:</p>
<!-- /wp:paragraph -->

<!-- wp:enlighter/codeblock -->
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">val set: Set[Int] = Set(1, 2, 5, 6, 9)

set.contains(2) // true
set(2) // same as above, returns true</pre>
<!-- /wp:enlighter/codeblock -->

<!-- wp:paragraph -->
<p>A <code>Set</code> offers a wide range of operations - full reference can be found <a href="https://www.scala-lang.org/api/current/scala/collection/immutable/Set.html" target="_blank" rel="noreferrer noopener">here</a>.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Where to use <code>Set</code>?</p>
<!-- /wp:paragraph -->

<!-- wp:list -->
<ul><li>Don't want duplicates</li><li>Need to quickly check for the presence of an element</li><li>No need to traverse</li></ul>
<!-- /wp:list -->

<!-- wp:heading -->
<h2><code>Map</code></h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>A <code>Map</code> is a collection of key-value pairs. Every key has a corresponding value assigned to it. Keys have to be unique, in order to provide <code>O(1)</code> lookup time. Values, however, do not have to be unique. Let's see how we can create a <code>Map</code>:</p>
<!-- /wp:paragraph -->

<!-- wp:enlighter/codeblock -->
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">// A Map of Int to String mapping
val map: Map[Int, String] = Map(1 -> "one", 2 -> "two", 3 -> "three")

// Or an empty Map
val emptyMap: Map[String, String] = Map()</pre>
<!-- /wp:enlighter/codeblock -->

<!-- wp:paragraph -->
<p>The elements in the <code>Map</code>, are created using <code>key -&gt; value</code> syntax, although you can also use <code>(key, value)</code> if you prefer (first version is preferred though).</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>What's interesting about the <code>Map</code>, is how we can get a value, using a key. The default method to get a value is <code>get(key)</code> method. This method, however, returns an <code>Option[T]</code>, and not <code>T</code>. That is to accommodate for a situation when a key doesn't exist - instead of an exception, an <code>Option[None]</code> is returned. If you prefer getting straight value, the apply method will give you that (or exception if none found of course). Let's see how it looks:</p>
<!-- /wp:paragraph -->

<!-- wp:enlighter/codeblock -->
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">val map: Map[Char, Int] = Map('I' -> 1, 'V' -> 5, 'X' -> 10)

map.get('I') // returns Option[Int]
map.get('D') // returns Option[None]

map('V') // returns 5
map('C') // throws exception</pre>
<!-- /wp:enlighter/codeblock -->

<!-- wp:paragraph -->
<p>A <code>Map</code> offers a wide range of operations - full reference can be found <a href="https://www.scala-lang.org/api/current/scala/collection/Map.html" target="_blank" rel="noreferrer noopener">here</a>.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>You can learn more about <code>Option</code> in my <a href="https://bartoszgajda.com/2020/02/23/monads-in-scala-by-example/" target="_blank" rel="noreferrer noopener">blog post</a> on it.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Where to use <code>Map</code>?</p>
<!-- /wp:paragraph -->

<!-- wp:list -->
<ul><li>Need key-value storage</li><li>Need O(1) lookup and retrieval</li><li>Order is not important</li><li>No duplicate keys required</li></ul>
<!-- /wp:list -->

<!-- wp:heading -->
<h2><code>Vector</code></h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>A <code>Vector</code> is an indexed, ordered, and traversable sequence. Despite sounding quite complicated, it's quite popular, general-purpose data structure, thanks to its good balance between fast random selection and fast random functional updates. Let's see how to use them in practice:</p>
<!-- /wp:paragraph -->

<!-- wp:enlighter/codeblock -->
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">// A Vector of Integers
val vector: Vector[Int] = Vector(1, 2, 3, 5, 7, 11)

// Or an empty Vector
val emptyVector: Vector[String] = Vector()</pre>
<!-- /wp:enlighter/codeblock -->

<!-- wp:paragraph -->
<p>The <code>apply</code> method of <code>Vector</code>, simply gets and element, using and index in the vector. In this data structure, an index must be between zero and the length of a vector - otherwise, and <code>IndexOutOfBoundsException</code> is thrown:</p>
<!-- /wp:paragraph -->

<!-- wp:enlighter/codeblock -->
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">val vector: Vector[String] = Vector("one", "two", "three")

vector(0) // returns "one"
vector(3) // exception</pre>
<!-- /wp:enlighter/codeblock -->

<!-- wp:paragraph -->
<p>A <code>Vector</code> offers a wide range of operations - full reference can be found <a href="https://www.scala-lang.org/api/current/scala/collection/immutable/Vector.html" target="_blank" rel="noreferrer noopener">here</a>.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Where to use <code>Vector</code>?</p>
<!-- /wp:paragraph -->

<!-- wp:list -->
<ul><li>Need fast random access and updates</li><li>Need fast append/prepend/tail operations</li><li>Must be traversable</li><li>Ordering matters</li></ul>
<!-- /wp:list -->

<!-- wp:heading -->
<h2><code>List</code></h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>The last collection is the easiest and therefore popular among simple use cases - <code>List</code>. This collection is implemented as a linked list, which represents ordered collections. Let's see how to use a <code>List</code>:</p>
<!-- /wp:paragraph -->

<!-- wp:enlighter/codeblock -->
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">// List of Strings
val list: List[String] = List("blue", "red", "yellow")

// Empty List
val emptyList: List[Int] = List()</pre>
<!-- /wp:enlighter/codeblock -->

<!-- wp:paragraph -->
<p>As mentioned above, a <code>List</code> is implemented as a linked list. This means, that we can create a list, using prepend operator <code>::</code> and a Nil, which represents empty list. This can be done like this: </p>
<!-- /wp:paragraph -->

<!-- wp:enlighter/codeblock -->
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">// Same as example from above
val list: List[String] = "blue" :: ("red" :: ("yellow" :: Nil))

// And an empty List
val emptyList = Nil</pre>
<!-- /wp:enlighter/codeblock -->

<!-- wp:paragraph -->
<p>A <code>List</code> offers a wide range of operations - full reference can be found <a href="https://www.scala-lang.org/api/current/scala/collection/immutable/List.html" target="_blank" rel="noreferrer noopener">here</a>.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Where to use <code>List</code>?</p>
<!-- /wp:paragraph -->

<!-- wp:list -->
<ul><li>Have to be traversable</li><li>Need O(1) prepending and reading of head element</li><li>Can tolerate O(n) appending and reading of internal elements</li><li>Don't need random access</li></ul>
<!-- /wp:list -->

<!-- wp:heading -->
<h2>Summary</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>I hope you have found this post useful. If so, don’t hesitate to like or share this post. Additionally, you can follow me on my social media if you fancy so 🙂</p>
<!-- /wp:paragraph -->