smeeb smeeb - 3 months ago 9
Scala Question

Modifying generic maps in Scala

I'm new to the Scala landscape after spending the last 10 years in Java and the last ~year in Groovy. Hi Scala!

For the life of me I can't seem to get the following code snippet to compile, and its just complicated enough to the point where the Google Gods aren't helping me.

I have a map that will contain Strings for keys and Lists of Tuples for values. The tuples will be a String-Long pair. In Groovy this would look like:

Map<String,List<Tuple2<String,Long>>> data = [:]


I need to be able to add and modify keys and values for this map. Specifically, I need to:


  1. Add to the List of Tuples for existing keys

  2. If a key doesn't exist, instantiate a new List of Tuples, and then add the key and list as a map entry



In Groovy this would look like:

Map<String,List<String,Long>> data = [:]

def addData(String key, String message) {
Long currTime = System.currentTimestampInMillis()
Tuple2<String,Long> tuple = new Tuple2<String,Long>(message, tuple)

if(data.contains(key)) {
data.key << tuple
} else {
data[key] = new List<Tuple2<String,Long>>()
data.key << tuple
}
}


I'm trying to do this in Scala, albeit unsuccessfully.

My best attempt thus far:

object MapUtils {
// var data : Map[String,ListBuffer[(String,Long)]] = Map()
val data = collection.mutable.Map[String, ListBuffer[(String, Long)]]()

def addData(key : String, message : String) : Unit = {
val newTuple = (message, System.currentTimeMillis())
val optionalOldValue = data.get(key)

optionalOldValue match {
case Some(olderBufferList) => olderBufferList += newTuple
case None => data
.put(key, ListBuffer[(String, Long)](newTuple))
}
}
}


Complains with this compiler error on the
case Some(olderBufferList) => olderBufferList += newTuple
line:

value += is not a member of Any


Any ideas what I can do to get this compiling & working?

Answer

You are missing an import for ListBuffer. The following code works perfectly fine in 2.9.1 (tested on TryScala), 2.11.7 (tested on IDEOne) and 2.11.8. Note the only addition is the first line adding the import:

import collection.mutable.ListBuffer

object MapUtils {
    // var data : Map[String,ListBuffer[(String,Long)]] = Map()
    val data = collection.mutable.Map[String, ListBuffer[(String, Long)]]()

    def addData(key : String, message : String) : Unit = {
        val newTuple = (message, System.currentTimeMillis())
        val optionalOldValue = data.get(key)

        optionalOldValue match {
            case Some(olderBufferList) => olderBufferList += newTuple
            case None => data
                .put(key, ListBuffer[(String, Long)](newTuple))
        }
    }
}

MapUtils.addData("123", "message 1")
MapUtils.addData("456", "message 2")

MapUtils.data
//=> Map(456 -> ListBuffer((message 2,1472925061065)), 123 -> ListBuffer((message 1,1472925060926)))