如何在 Scala 中使用默认操作实现 Map

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5830458/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-22 02:59:09  来源:igfitidea点击:

How to implement Map with default operation in Scala

scalascala-collections

提问by Lukasz

class DefaultListMap[A, B <: List[B]] extends HashMap[A, B] {
    override def default(key: A) = List[B]() 
  }

I wan't to create map A -> List[B]. In my case it is Long -> List[String]but when I get key from map that doesn't have value I would like to create empty Listinstead of Exceptionbeing thrown. I tried different combinations but I don't know how to make code above pass the compiler.

我不想创建 map A -> List[B]。在我的情况下,Long -> List[String]但是当我从地图中获得没有价值的键时,我想创建空List而不是Exception被抛出。我尝试了不同的组合,但我不知道如何使上面的代码通过编译器。

Thanks in advance.

提前致谢。

回答by Ilya Klyuchnikov

Why not to use withDefaultValue(value)?

为什么不使用 withDefaultValue(value)?

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()

回答by oxbow_lakes

Rather than using applyto access the map, you could always use get, which returns Option[V]and then getOrElse:

而不是apply用于访问地图,您可以始终使用get,它返回Option[V]然后getOrElse

map.get(k) getOrElse Nil

One great feature of the scalazfunctional-programming libraryis the unary operator ~, which means "or zero",as long as the value type has a "zero" defined (which Listdoes, the zero being Nilof course). So the code then becomes:

scalaz函数式编程库的一个重要特性是一元运算符~,这意味着“或零”,只要值类型定义了“零”(List确实如此,零Nil当然是)。所以代码就变成了:

~map.get(k)

This is doubly useful because the same syntax works where (for example) your values are Int, Doubleetc (anything for which there is a Zerotypeclass).

这是极为有用的,因为相同的语法工程时(例如)你的价值观是IntDouble等(任何事情上有一个Zero类型类)。



There has been a great deal of debate on the scala mailing list about using Map.withDefaultbecause of how this then behaves as regards the isDefinedAtmethod, among others. I tend to steer clear of it for this reason.

在 Scala 邮件列表上有很多关于使用的争论,Map.withDefault因为它在isDefinedAt方法方面的表现等等。出于这个原因,我倾向于避开它。

回答by kassens

There's a method withDefaultValueon Map:

有一个方法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()

回答by Landei

Why do you want to manipulate a map when it has already a method for this?

当地图已经有一个方法时,你为什么要操作它?

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)

回答by tharindu_DG

withDefaultcan also be used.

也可以使用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]

Example:

例子:

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

Hope this helps.

希望这可以帮助。