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.