2011-04-29 53 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 

希望这有助于。

相关问题