2011-09-22 60 views
4

我認爲這是可以做到如下有沒有辦法讓斯卡拉HashMap中自動初始化值?

val hash = new HashMap[String, ListBuffer[Int]].withDefaultValue(ListBuffer()) 
hash("A").append(1) 
hash("B").append(2) 
println(hash("B").head) 

然而上述打印1.直觀的價值,我想

hash("B").append(2) 

像做幕後以下

if (!hash.contains("B")) hash.put("B", ListBuffer()) 

回答

7

withDefaultValue使用正是每一次相同的值。在你的情況下,這是空的ListBuffer是由大家分享。

如果使用withDefault相反,你可以生成一個新的ListBuffer每一次,但它不會得到保存。

那麼,你真的很喜歡的是會知道添加的默認值的方法。您可以在包裝類中創建這樣的方法,然後寫一個隱式轉換:

class InstantiateDefaults[A,B](h: collection.mutable.Map[A,B]) { 
    def retrieve(a: A) = h.getOrElseUpdate(a, h(a)) 
} 
implicit def hash_can_instantiate[A,B](h: collection.mutable.Map[A,B]) = { 
    new InstantiateDefaults(h) 
} 

現在你的代碼根據需要(除了額外的方法名稱,你可以挑選是,如果你想更短)的工作原理:

val hash = new collection.mutable.HashMap[ 
    String, collection.mutable.ListBuffer[Int] 
].withDefault(_ => collection.mutable.ListBuffer()) 

scala> hash.retrieve("A").append(1) 

scala> hash.retrieve("B").append(2) 

scala> hash("B").head 
res28: Int = 2 

注意,該解決方案(與隱含的)並不需要知道的默認值本身好,所以你可以這樣做一次,然後默認與 - 除了你的心臟的內容。

+0

是否有某種方式來覆蓋哈希(「B」)的默認行爲追加(2)? – deltanovember

+3

你可以擴展'apply',但是很快就會變得醜陋。你最好使用一個單獨的方法國際海事組織。 –

+2

@deltanova可以皮條客'HashMap中[A,ListBuffer [B]]'有一種方法'DEF追加[A,B](鍵:A,值:B)= getOrElseUpdate(鍵)(新LB ...) .append(值)'。 – ziggystar

10

使用getOrElseUpdate在接入點提供的默認值:

scala> import collection.mutable._ 
import collection.mutable._ 

scala> def defaultValue = ListBuffer[Int]() 
defaultValue: scala.collection.mutable.ListBuffer[Int] 

scala> val hash = new HashMap[String, ListBuffer[Int]] 
hash: scala.collection.mutable.HashMap[String,scala.collection.mutable.ListBuffer[Int]] = Map() 

scala> hash.getOrElseUpdate("A", defaultValue).append(1) 

scala> hash.getOrElseUpdate("B", defaultValue).append(2) 

scala> println(hash("B").head) 
2