正如丹尼爾寫道,嘗試用Double編寫Java風格的部分問題來自於Scala中的Double
是scala.Double
而不是java.lang.Double
。如果你想在風格的Java編程,你將不得不大意如下走:
//
// 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)
斯卡拉2.8中包含Scala的包裝爲ConcurrentMap
S,所以你可以很容易地避免java.lang.Double
問題VS scala.Double
。我會保持一段時間的程序結構。
//
// 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)
在變型b)中不存在表示缺少的值作爲0.0D非彼java.lang.Double
不與運營商和拳擊發揮很好的問題既沒有問題。但是,a)和b)版本對於它們的併發行爲都存在疑問。 Mansoor的代碼使用ConcurrentHashMap
,其目的是允許同時訪問地圖。在原始版本的代碼中,有可能在獲取舊的value
和存儲value + time
之間丟失地圖更新。 以下變體c)試圖避免這個問題。
//
// 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)
謝謝你的解釋 – 2010-06-08 16:02:20