Home > Net >  How to update value of a key in a immutable tree map in Scala
How to update value of a key in a immutable tree map in Scala

Time:12-09

I'm using Scala 2.11 and i'm trying to update the value of a key in the tree map. I tried using updated:

private val xyz = List(0, 100000, 500000, 1000000)
private val abc = List (0, 5, 25, 50)
private var a = TreeMap.empty[Int, TreeMap[Int, Int]]    xyz.map { 
        aa => aa -> (TreeMap.empty[Int, Int]    abc.map(bb => bb -> 0))
    }
a(xyz(0)).foreach { 
        case (key, value) =>
            if (key < 50) {
                a(xyz(0)) = a(xyz(0)).updated(key, 5)
            }
    }

And got the error:

 value update is not a member of scala.collection.immutable.TreeMap[Int,scala.collection.immutable.TreeMap[Int,Int]]

Is it possible to update it? Or could someone please help me replicate the logic using a Java Tree Map since that will also allow me to use floorEntry and ceilingEntry functions. I tried converting to java tree map and it generated a regular map, not a tree map:

private var a = TreeMap.empty[Int, TreeMap[Int, Int]]    xyz.map { 
    aa => aa -> (TreeMap.empty[Int, Int]    abc.map(bb => bb -> 0)).asJava
}
private var b = a.asJava

CodePudding user response:

You are getting confused between var/val and mutable/immutable.

I think you correctly understood the difference between val and var, that the former is an immutable variable and later is mutable. ie, if you try to reassign the object assigned as val you will get an error.

import scala.collection.immutable.TreeMap

val tm = TreeMap(1 -> 1, 2 -> 2, 3 -> 3)
tm = TreeMap(1->2)
      ^
   error: reassignment to val

But a var can be mutated:

import scala.collection.immutable.TreeMap

var tm = TreeMap(1 -> 1, 2 -> 2, 3 -> 3)
tm = TreeMap(1->2)
// mutated tm

Notice that in the latter case, even though we are mutating the variable, we are not mutating the collection itself, we are assigning a new TreeMap. As we were using scala.collection.immutable.TreeMap it cant be mutated.

Instead, if we had used scala.collection.mutable.TreeMap, it has an update function

import scala.collection.mutable.TreeMap

val tm = TreeMap(1 -> 1, 2 -> 2, 3 -> 3)
tm.update(1, 5)
tm //TreeMap(1 -> 5, 2 -> 2, 3 -> 3)

Once you change scala.collection.immutable.TreeMap to scala.collection.mutable.TreeMap, this will work

a(xyz(0)).foreach{ case (key, value) =>
  if(key < 50){
    a(xyz(0)) = a(xyz(0)).updated(key, 5) //addOne(key, 5) if 2.13 
  }
}

CodePudding user response:

It is not possible to update an immutable object, you can only create a new immutable object from the old one. So the code needs to create a new TreeMap from the original one with different values as necessary.

The code looks like this:

val newMap = a.map{
  case (k, v) if k == xyz(0) =>
    k -> v.map {
      case (k2, v2) if k2 < 50 =>
        k2 -> 5
      case (k2, v2) =>
        k2 -> v2
    }
  case (k, v) =>
    k -> v
}

This breaks down to an outer map that looks for matching keys in the outer TreeMap, and an inner map that looks for matching keys in the inner TreeMap. Pattern matching (case) is used to implement the match tests, and also to extract the keys and values.

Each map has one case that selects the values to be modified, and a second case that leaves other values unchanged. The first case returns the original key with a modified value while the second case just returns the original values (k -> v).


Also note that var applies to a variable, not the contents of a variable. It indicates whether the variable can be updated to refer to a different object, but says nothing about whether the object that the variable refers to can be updated. var is rarely used in Scala because it goes against a clean functional design.

  • Related