Scala映射具有相同类型的键,但值的不规则类型和值的子类型本身是不规则的

时间:2011-07-09 10:29:45

标签: scala

  

可能重复:
  Scala map containing mix type values

我有一种情况,在之前的groovy程序中构建一个像

这样的结构
mp = [k1: "string", k2: [d1: [1,2,3], d2: 1975], k3: 345, k4: ["one","two"]]

相当于:

[String: String, String: Map[String, Any], String: Int, String: List[String]]

该函数将mp返回给调用函数。

你可以看到mp map的值是不规则的。我正在用scala重写程序。

在scala中我必须将mp表示为Map [String,Any],但是这会导致在使用mp的测试代码中使用isInstanceOf和asInstanceOf进行舞蹈,这导致了大量的scala样板代码。 Scala抱怨List [String]的主要原因不能转换为Any。例如。

scala有更好的解决方案吗?

仔细观察时,这个问题与我之前的问题有所不同。在这个问题中,你可以看到关键k2的值[d1:[1,2,3],d2:“string”]本身就是不规则的地图。

我提出了这个解决方案: 创建另一个scala类,如:

class MakeMap  {

// lot of code here
....

val k1: String  = // put here value found in logic above
val k2 : Map[String, Any]  // here is the issue, I am again forced to use Any
val k3 : List[String]  // put here value found in logic above

}

在测试代码中:

val m1 = new MakeMap()
m1.k1  // very easy to access value, also gets rid of scala verbose syntax to access vale
      // in map like getOrElse
m1.k2  // this is the issue, it seesm I have to define yet another class
m1.k3 // again easy

2 个答案:

答案 0 :(得分:2)

scala-user上的

This消息似乎解决了您感兴趣的用例?

答案 1 :(得分:1)

如果您正在将代码从Groovy重写为Scala,我想您正在寻找性能和安全性。因此,尽量避免使用地图来存储所有内容,因为您可能会松开两者。尝试事先定义所需的数据结构,并使用可以看作不可变结构的case class

例如,等效于Groovy值:

[k1: "string", k2: [d1: [1,2,3], d2: 1975], k3: 345, k4: ["one","two"]]

可以定义为:

case class Outer( k1: String, k2: Inner, k3: Int, k4: List[String] )
case class Inner( d1: List[Int], d2: Int )

然后您可以将对象mp创建为:

val mp = Outer( "string", Inner( List(1,2,3), 1975 ), 345, List("one","two") )

并访问以下成员:

val x = mp.k2.d2

当然,给出明智的名字。首先尝试尽可能限制您的类型,避免AnyAnyRefAnyVal。通常可以这样做。