As Daniel wrote, part of the problem trying to write Java-style using Double is because Double in Scala is scala.Double , not java.lang.Double . If you want to program a Java style, you will need to run the following lines:
// // a) Java style, with concurrency problem // import java.lang.{Double=>JDouble} import java.util.concurrent.ConcurrentHashMap val map = new ConcurrentHashMap[String, JDouble] def update(name: String, time: Double) { val value: JDouble = map.get(name) if (value eq null) map.put(name, time) else map.put(name, JDouble.valueOf(value.doubleValue + time)) } update("foo", 42.0d) update("foo", 41.0d) assert(map.get("foo") == 83.0d)
Scala 2.8 contains the Scala shell for ConcurrentMap s, so you can easily avoid the java.lang.Double vs scala.Double . I will keep the program structure for a moment.
// // b) Scala style, with concurrency problem. // import collection.JavaConversions._ import collection.mutable.ConcurrentMap import java.util.concurrent.ConcurrentHashMap val map: ConcurrentMap[String, Double] = new ConcurrentHashMap[String,Double]() def update(name: String, time: Double) { map.get(name) match { case None => map.put(name, time) case Some(value) => map.put(name, value + time) } } update("foo", 42.0d) update("foo", 41.0d) assert(map("foo") == 83.0d)
In option b) above, there is not a single problem of representing the missing value as 0.0d, nor a problem that java.lang.Double does not play well with statements and boxing. But both versions a) and b) are questionable regarding their concurrency behavior. The Mansoor code uses ConcurrentHashMap , which aims to allow simultaneous access to the map. In the original version of the code, there is a chance that the map update will be lost between getting the old value and saving value + time . Option c) below tries to avoid this problem.
// // c) Scala style, hopefully safe for concurrent use ;) // import collection.JavaConversions._ import collection.mutable.ConcurrentMap import java.util.concurrent.ConcurrentHashMap val map: ConcurrentMap[String, Double] = new ConcurrentHashMap[String,Double]() def update(name: String, time: Double) { val valueOption: Option[Double] = map.putIfAbsent(name, time) def replace(value: Double) { val replaced = map.replace(name, value, value + time) if (!replaced) { replace(map(name)) } } valueOption foreach { replace(_) } } update("foo", 42.0d) update("foo", 41.0d) assert(map("foo") == 83.0d)