2011-04-29 37 views
33
class DefaultListMap[A, B <: List[B]] extends HashMap[A, B] { 
    override def default(key: A) = List[B]() 
    } 

我不想創建地圖A -> List[B]。在我的情況下,它是Long -> List[String],但是當我從地圖中獲得沒有價值的密鑰時,我想創建空的List而不是Exception被引發。我嘗試了不同的組合,但是我不知道如何使上面的代碼通過編譯器。如何在Scala中實現具有默認操作的地圖

在此先感謝。

+0

我在我的情況下得到周圍使用 '代碼 VAL地圖=新的HashMap [長,列表[字符串](){ 覆蓋高清默認(鍵:長)=列表[字符串]() } ' – Lukasz 2011-04-29 09:57:19

回答

78

爲什麼不使用withDefaultValue(價值)?

scala> val m = Map[Int, List[String]]().withDefaultValue(List()) 
m: scala.collection.immutable.Map[Int,List[String]] = Map() 

scala> m(123) 
res1: List[String] = List() 
3

爲什麼你想操縱一個地圖,當它已經有一個方法呢?

val m = Map(1L->List("a","b"), 3L->List("x","y","z")) 
println(m.getOrElse(1L, List("c"))) //--> List(a, b) 
println(m.getOrElse(2L, List("y"))) //--> List(y) 
+0

查看我對@oxbow_lakes的評論:這與OP所要求的不一樣。它管理地圖訪問時的默認值,而不是在地圖創建時。 – 2017-01-04 09:27:04

18

而不是使用apply訪問地圖,你總是可以使用get,它返回Option[V]然後getOrElse

map.get(k) getOrElse Nil 

其中scalaz編程功能庫的強大功能是一元運算符~,意思是「或零」,只要值類型定義爲「零」(即List,零爲01當然是)。因此,代碼就變成了:

~map.get(k) 

這是極爲有用的,因爲相同的語法工程時(例如)你的價值觀是IntDouble等(任何事情上有一個Zero類型類)。


有一直是人們爭論的一個很大的斯卡拉郵件列表中有關使用Map.withDefault因爲這個再怎麼表現爲關於isDefinedAt方法,等等。出於這個原因,我傾向於避開它。

+0

有趣的答案。然而,這一舉動是從地圖創建到地圖訪問的未定義項目的管理。在我的情況下,我需要將一個Map傳遞給一個已經有自己默認行爲的方法,我想重寫(用於測試)。而且我無法更改讀取地圖的代碼。 – 2017-01-04 09:24:20

9

有一個方法withDefaultValueMap

scala> val myMap = Map(1 -> List(10), 2 -> List(20, 200)).withDefaultValue(Nil) 
myMap: scala.collection.immutable.Map[Int,List[Int]] = Map((1,List(10)), (2,List(20, 200))) 

scala> myMap(2) 
res0: List[Int] = List(20, 200) 

scala> myMap(3) 
res1: List[Int] = List() 
+8

還有一個'withDefault',它具有一個函數。 – 2011-04-29 19:39:58

2

withDefault也可以使用。

/** The same map with a given default function. 
* Note: `get`, `contains`, `iterator`, `keys`, etc are not affected 
* by `withDefault`. 
* 
* Invoking transformer methods (e.g. `map`) will not preserve the default value. 
* 
* @param d  the function mapping keys to values, used for non-present keys 
* @return  a wrapper of the map with a default value 
*/ 
def withDefault[B1 >: B](d: A => B1): immutable.Map[A, B1] 

例子:

scala> def intToString(i: Int) = s"Integer $i" 
intToString: (i: Int)String 

scala> val x = Map[Int, String]().withDefault(intToString) 
x: scala.collection.immutable.Map[Int,String] = Map() 

scala> x(1) 
res5: String = Integer 1 

scala> x(2) 
res6: String = Integer 2 

希望這有助於。

相關問題