类型 Map[String,Any] 中的非变量类型参数 String
Non-variable type argument String in type Map[String,Any]
我有一个简单的方法可以从哈希图中检索嵌套键。我需要在 Map[String,Any]
上进行模式匹配,以便我可以继续迭代嵌套数据,直到得到一个固定值:
def get(map: Map[String, Any], key: String): Any = {
var fields: mutable.Seq[String] = key.split('.')
var currentKey: String = fields.head
var currentValue: Any = map
while (fields.nonEmpty && currentValue.isInstanceOf[Map[String, Any]]) {
currentKey = fields.head
fields = fields.drop(1)
currentValue match {
case m: Map[String, Any] => currentValue = m.getOrElse(currentKey, None)
case _ =>
}
}
if (fields.nonEmpty) None else currentValue
}
当我只在 scala 中使用它时它可以工作,但如果从 java 调用它,我会得到错误 non-variable type argument String in type scala.collection.immutable.Map[String,Any]
。
我见过一些其他解决方案,这些解决方案要求您重构代码并将地图包装在一个案例中 class,但这对所有依赖此方法的代码来说都是非常具有破坏性的。有没有更简单的修复方法?
由于类型擦除,您无法在 Map[String,Any]
上进行模式匹配。编译器会对此发出警告。此代码仅在 Map[_,_]
上匹配,因此它会在任何键类型上成功,而不仅仅是 String
.
因此该方法本身存在缺陷,从 Java 调用似乎暴露了使用 Scala 时未出现的缺陷。
由于您还没有使用 Java 中的这个,我会切换到 Java 代码的类型安全实现,然后尽快将遗留代码迁移到这个版本。虽然这可能具有破坏性,但它会修复引入错误代码的设计错误,因此应该尽早完成。 (每当你看到 Any
用作值类型时,很可能是设计在某个时候出错了)
类型安全版本并不难,这里是一个大纲实现:
class MyMap[T] {
trait MapType
case class Value(value: T) extends MapType
case class NestedMap(map: Map[String, MapType]) extends MapType
def get(map: Map[String, MapType], key: String): Option[T] = {
def loop(fields: List[String], map: Map[String, MapType]): Option[T] =
fields match {
case Nil =>
None
case field :: rest =>
map.get(field).flatMap{
case Value(res) => Some(res)
case NestedMap(m) => loop(rest, m)
}
}
loop(key.split('.').toList, map)
}
}
实际上 MyMap
应该实际保存 Map
数据而不是将其传递给 get
,并且会有安全构建嵌套地图的方法。
我有一个简单的方法可以从哈希图中检索嵌套键。我需要在 Map[String,Any]
上进行模式匹配,以便我可以继续迭代嵌套数据,直到得到一个固定值:
def get(map: Map[String, Any], key: String): Any = {
var fields: mutable.Seq[String] = key.split('.')
var currentKey: String = fields.head
var currentValue: Any = map
while (fields.nonEmpty && currentValue.isInstanceOf[Map[String, Any]]) {
currentKey = fields.head
fields = fields.drop(1)
currentValue match {
case m: Map[String, Any] => currentValue = m.getOrElse(currentKey, None)
case _ =>
}
}
if (fields.nonEmpty) None else currentValue
}
当我只在 scala 中使用它时它可以工作,但如果从 java 调用它,我会得到错误 non-variable type argument String in type scala.collection.immutable.Map[String,Any]
。
我见过一些其他解决方案,这些解决方案要求您重构代码并将地图包装在一个案例中 class,但这对所有依赖此方法的代码来说都是非常具有破坏性的。有没有更简单的修复方法?
由于类型擦除,您无法在 Map[String,Any]
上进行模式匹配。编译器会对此发出警告。此代码仅在 Map[_,_]
上匹配,因此它会在任何键类型上成功,而不仅仅是 String
.
因此该方法本身存在缺陷,从 Java 调用似乎暴露了使用 Scala 时未出现的缺陷。
由于您还没有使用 Java 中的这个,我会切换到 Java 代码的类型安全实现,然后尽快将遗留代码迁移到这个版本。虽然这可能具有破坏性,但它会修复引入错误代码的设计错误,因此应该尽早完成。 (每当你看到 Any
用作值类型时,很可能是设计在某个时候出错了)
类型安全版本并不难,这里是一个大纲实现:
class MyMap[T] {
trait MapType
case class Value(value: T) extends MapType
case class NestedMap(map: Map[String, MapType]) extends MapType
def get(map: Map[String, MapType], key: String): Option[T] = {
def loop(fields: List[String], map: Map[String, MapType]): Option[T] =
fields match {
case Nil =>
None
case field :: rest =>
map.get(field).flatMap{
case Value(res) => Some(res)
case NestedMap(m) => loop(rest, m)
}
}
loop(key.split('.').toList, map)
}
}
实际上 MyMap
应该实际保存 Map
数据而不是将其传递给 get
,并且会有安全构建嵌套地图的方法。