Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Diving Into Scala Maps

DZone's Guide to

Diving Into Scala Maps

Let's explore Scala maps, and the myriad ways you can iterate and transform over them while learning important lessons about their mutability.

· Java Zone
Free Resource

Managing a MongoDB deployment? Take a load off and live migrate to MongoDB Atlas, the official automated service, with little to no downtime.

A Scala Map is a collection of a Key-value pair. A map cannot have duplicate keys, but different keys can have same values. Maps in Scala are not language syntax. They are library abstractions that you can extend and adapt.

Scala provides mutable and immutable alternatives for maps. The class hierarchy for Scala maps is shown below:

Screenshot from 2017-04-28 18-34-09

Image is taken from Programming in Scala by Martin Odersky

There’s a base Map trait in package scala.collection and two subtraits – a mutable Map in scala.collection.mutable and an immutable one in scala.collection.immutable. By default, a Scala Map is immutable, but if you want to use mutable one, then you need to import mutable Map by using the statement: import scala.collection.mutable

Creating and initializing a map is easy:

val tasks = Map(1 -> “Book movie tickets”,2 -> “Go shopping”)


The Scala compiler transforms a binary operation expression like 1 -> “Book movie ticket” into (1).->(“Book movie ticket”). Thus, when you say 1 -> “Book movie ticket”, you are actually calling a method named -> on an integer with the value 1, passing in a string with the value “Book movie ticket”. This -> method, which you can invoke on any object in a Scala program, returns a two-element tuple containing the key and value.

Maps are Iterables of pairs of keys and values (also named mappings or associations). Scala’s Predef object offers an implicit conversion that lets you write key -> value as an alternate syntax for the pair (key, value). Therefore, Map(1 -> “Book movie ticket” , 2 ->”Go shopping”) means exactly the same as Map((1,”Book movie ticket”),(2,”Go shopping”))

As for creating a mutable map:

import scala.collection.mutable

val tasks = mutable.Map[Int,String]()

tasks += (1 -> “Book a movie ticket”)

tasks += (2 -> “Go shopping”)


Basic Map Operations

  1. keys: returns an iterable containing each key in the map.
  2. values:  returns an iterable containing each value in the map.
  3. isEmpty: returns true if the map is empty otherwise false.

For example:

val subjects = Map(1 -> “DS”,2 -> “C++”,3 -> “Java”)

subjects.keys

subjects.values

subjects.isEmpty


Will give the result:

res0: Iterable[Int] = Set(1, 2, 3)

res1: Iterable[String] = MapLike.DefaultValuesIterable(DS, C++, Java)

res2: Boolean = false


Map operations fall into the following categories.

Lookups

These operations turn maps into partial functions from keys to values. Lookup operations include apply, get, getOrElse, contains, and isDefinedAt. The fundamental lookup method for a map is:

def get(key): Option[Value]


The operation “m get key” tests whether the map contains an association for the given key. If so, it returns the associated value in a Some. If no key is defined in the map, get returns None. Maps also define an apply method that returns the value associated with a given key directly, without wrapping it in an Option. If the key is not defined in the map, an exception is raised.

Let’s say we have a Map:    

val subjects = Map(1 -> “DS”,2 -> “C++”,3 -> “Java”)


TheGet operation will return the value associated with the key in map subjects, such as an option, or None if not found.

subjects get(1) will result in res0: Option[String] = Some(DS).

The apply operation uses the value associated key in map subjects, or throws an exception if not found.

subjects(1) will result in  res1: String = DS.

getOrElse: The value associated key in the map, or the default value if not found.

subjects getOrElse(4,”DCN”) will result in res2: String = DCN.

Additions and Updates  

These operations let you add new bindings to a map or change existing bindings. + , ++ , and updated are included in this category.

Examples:

  • + operation: Used to add single element

subjects + (4 ->”Operating system”) will result in:

res0: scala.collection.immutable.Map[Int,String] = Map(1 -> DS, 2 -> C++, 3 -> Java, 4 -> Operating system)


  • ++ operation: Used to add multiple Maps
val subjects = Map(1 -> “DS”,2 -> “C++”,3 -> “Java”)

val newSubjects = Map(3 -> “Scala”, 4 -> “c#”)

val listOfSubjects = subjects ++ newSubjects


will result in:

listOfSubjects: scala.collection.immutable.Map[Int,String] = Map(1 -> DS, 2 -> C++,
3 -> Scala, 4 -> c#)


  • updated operation: To update the value of a particular key.

subjects updated(1,”OS”) will result in:

res0: scala.collection.immutable.Map[Int,String] = Map(1 -> OS, 2 -> C++, 3 -> Java)


Removals

These operations remove bindings from a map. They include – and —

For example:

  • operation: Use to remove one element from Map.
val subjects = Map(1 -> “DS”,2 -> “C++”,3 -> “Java”)

subjects – 1


will result in:

res0: scala.collection.immutable.Map[Int,String] = Map(2 -> C++, 3 -> Java)


Subcollection Producers

These return a map’s keys and values separately in various forms. They include keys, keySet, keysIterator, valuesIterator, and values.

For example, take:

val subjects = Map(1 -> “DS”,2 -> “C++”,3 -> “Java”)


  • Keys returns an iterable containing each key in the map

subjects.keys will result in:

res0: Iterable[Int] = Set(1, 2, 3)

  • keySet returns a set containing each key in the map

subjects.keySet will result in:

res1: scala.collection.immutable.Set[Int] = Set(1, 2, 3)

  •   keysIterator: returns an iterator over all keys in the map

subjects.keysIterator.toSet will result in:

res2: Iterator[Int] = non-empty iterator

  • valuesIterator:  returns an iterator over all values that are associated with some key in the map

subjects.valuessIterator.toSet will result in:

res3: Iterator[String] = non-empty iterator


Transformations

Transformations produce a new map by filtering and transforming bindings of an existing map.They include filterKeys and mapValues

Example:

  • filterKeys: Filters the map by retaining only keys satisfying a predicate.
val subjects = Map(1 -> “DS”,2 -> “C++”,3 -> “Java”)

subjects.filterKeys(x => x%2 == 0)


will result in:

res0: scala.collection.immutable.Map[Int,String] = Map(2 -> C++)


  • mapValues: Transforms the map by applying a function to every retrieved value.
val values = Map( “a” -> 1, “b” -> 2 )

values.mapValues(_ * 2)


will result in:

res1: scala.collection.immutable.Map[String,Int] = Map(a -> 2, b -> 4)


Concatenating Two Maps

To concatenate two or more maps, we use the ++ operator or Map.++() method. While doing so, duplicate keys are removed and only the last value will be stored in the map. For example:

val subjects = Map(1 -> “DS”,2 -> “C++”,3 -> “Java”)

val newSubjects = Map(3 -> “Scala”, 4 -> “c#”)

subjects ++ newSubjects


This will result in:

res0: scala.collection.immutable.Map[Int,String] = Map(1 -> DS, 2 -> C++, 3 -> Scala, 4 -> c#)


Duplicate key 3, having value java, is replaced by a new value of 3.

Iterating Over Scala Maps

You can iterate over Map using several different techniques. For example, we have...

  • For loops:
val subjects = Map(1 -> “DS”,2 -> “C++”,3 -> “Java”)

for ((key, value) <- subjects){
    println(“key is : ” + key + ” its vaue is : ” + value)
}


  • Foreach loops:
val subjects = Map(1 -> “DS”,2 -> “C++”,3 -> “Java”)

subjects foreach{case (key,value) =>

println(“key is : ” + key +” its vaue is : ” + value)}


Understanding Mutable Variables With Immutable Collections

Mixing a mutable variable (var) with an immutable collection causes surprising behavior. While creating an immutable Map as a var, it appears you can somehow add new elements to it:

var subjects = Map(1 -> “DS”)

subjects += (2 -> “C++”)

subjects += (3 -> “Java”)


It looks like you’re mutating an immutable collection, but what’s really happening is that the subjects variable points to a new collection each time you use the += method.

The subjects variable is mutable — like a non-final field in Java — so it’s actually being reassigned to a new collection during each step.

The end result is as follows:

var subjects = Map(1 -> “DS”)

subjects += (1 -> “DS”,2 -> “C++”)

subjects += (1 -> “DS”,2 -> “C++”,3 -> “Java”)


When you first start working with Scala, the behavior of a mutable variable with an immutable collection can be surprising. To be clear about variables and values:

  • A mutable variable (var) can be reassigned to point at new data.
  • An immutable variable (val) is like a final variable in Java; it can never be reassigned.

MongoDB Atlas is the easiest way to run the fastest-growing database for modern applications — no installation, setup, or configuration required. Easily live migrate an existing workload or start with 512MB of storage for free.

Topics:
java ,scala ,maps ,mutability ,tutorial

Published at DZone with permission of Shivangi Gupta. See the original article here.

Opinions expressed by DZone contributors are their own.

THE DZONE NEWSLETTER

Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

X

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}