I am trying to implement a nested map in scala in play framework. what I am trying to achieve is a map which is of type Map[String, Map[Long,Int]]
. I am not able to assign the value of the parent map which is itself a map. The application is compiling properly but the value is not getting updated. Can you please suggest what I am doing wrong and how to assign a map value to another map?
import java.util.concurrent.ConcurrentHashMap
import scala.collection._
import scala.collection.convert.decorateAsScala._
import scala.collection.JavaConversions.mapAsScalaMap
case class Events(eventType: String, timeStamp: Long)
object Events {
var eventMap = new ConcurrentHashMap[String, ConcurrentHashMap[Long,Int]]()
def save(events: Events) = {
var eventsKey: String = ""
var count: Int = 1
var timeKey: Long = 0L
var newEntry: Boolean = false
eventsKey = events.eventType
var countMap = new ConcurrentHashMap[Long,Int]()
countMap.clear()
if (eventMap.containsKey(eventsKey)) {
countMap = eventMap.get(eventsKey) // this is not working
timeKey = events.timeStamp
if (countMap.containsKey(timeKey)) {
count = countMap(timeKey) + 1
countMap.put(timeKey, count)
eventMap.put(eventsKey, countMap)
} // End of counter check
else {
newEntry = true
}
} // End of if event key check
else {
newEntry = true
} // End of else event key check
if (newEntry) {
countMap.putIfAbsent(timeKey, 1)
eventMap.putIfAbsent(eventsKey, countMap)
}
}
}
The problem is happening because you are only setting temporary timeKey
inside the if, and you still need this value outside of the if. This will make your program to always insert the first timeStamp
of a given eventType
as 0
:
Events.save(Events("aa", 222)) // {aa={0=1}}
Events.save(Events("aa", 333)) // {aa={0=1, 333=1}}
Events.save(Events("aa", 333)) // {aa={0=1, 333=2}}
Events.save(Events("bb", 444)) // {aa={0=1, 333=2}, bb={0=1}}
To fix it, just move the code out of the if
:
...
var newEntry: Boolean = false
eventsKey = events.eventType
timeKey = events.timeStamp // <--- This fixes it
var countMap = new ConcurrentHashMap[Long,Int]()
countMap.clear()
if (eventMap.containsKey(eventsKey)) {
countMap = eventMap.get(eventsKey) //this is not working
if (countMap.containsKey(timeKey)) {
count = countMap(timeKey) + 1
...
Now when you run, you get:
Events.save(Events("aa", 222)) // {aa={222=1}}
Events.save(Events("aa", 333)) // {aa={333=1, 222=1}}
Events.save(Events("aa", 333)) // {aa={333=2, 222=1}}
Events.save(Events("bb", 444)) // {aa={333=2, 222=1}, bb={444=1}}
I know you didn't asked about it, but I thought it would be nice to have a more idiomatic scala code:
case class Event(eventType: String, timeStamp: Long)
object Event {
val eventMap = new ConcurrentHashMap[String, ConcurrentHashMap[Long,Int]]()
def save(event: Event) = {
val Event(eventKey, timeKey) = event
val countMap = eventMap.getOrElse(eventKey, new ConcurrentHashMap[Long,Int]())
val count = countMap.getOrElse(timeKey, 0) + 1
countMap.put(timeKey, count)
eventMap.put(eventKey, countMap)
}
}
PS: I renamed Events
to Event
PS2: Notice how the bug you stumbled upon is more difficult to happen when you are programming in a more idiomatic way. :)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.