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

发布于 2024-11-04 02:08:11 字数 342 浏览 0 评论 0原文

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

我不想创建地图 A ->列表[B]。就我而言,它是 Long -> List[String] 但是当我从地图中获取没有值的键时,我想创建空的 List 而不是抛出 Exception 。我尝试了不同的组合,但我不知道如何使上面的代码通过编译器。

提前致谢。

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 List instead of Exception being thrown. I tried different combinations but I don't know how to make code above pass the compiler.

Thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

孤独患者 2024-11-11 02:08:11

为什么不使用 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()

Why not to use 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()
熊抱啵儿 2024-11-11 02:08:11

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

map.get(k) getOrElse Nil

scalaz函数式编程库的一个重要功能是一元运算符~,它的意思是“或零”,只要值类型定义了一个“零”(List 就是这样,零当然是 Nil)。所以代码就变成了:

~map.get(k)

这是双重有用的,因为相同的语法适用于(例如)您的值为 IntDouble 等(任何有 >零 类型类)。


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

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

map.get(k) getOrElse Nil

One great feature of the scalaz functional-programming library is the unary operator ~, which means "or zero",as long as the value type has a "zero" defined (which List does, the zero being Nil of course). So the code then becomes:

~map.get(k)

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


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

嘦怹 2024-11-11 02:08:11

Map 上有一个方法 withDefaultValue

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

There's a method withDefaultValue on Map:

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()
生寂 2024-11-11 02:08:11

当地图已经有方法时,为什么还要操作地图呢?

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)

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)
¢好甜 2024-11-11 02:08:11

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

希望这会有所帮助。

withDefault can also be used.

/** 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文