Scala:避免类型擦除
Scala: avoid type erasure
来自以下代码:
type Structure = Map[String, Any]
def getStructureSourceNames(structuresDesc: Structure): Iterable[String] = {
val subColsDesc: Map[String, String] =
structuresDesc.filter(_._2.isInstanceOf[String]).asInstanceOf[Map[String, String]]
val subStructuresDesc: Map[String, Structure] = structuresDesc
.filter(_._2.isInstanceOf[Map[String, Structure]])
.asInstanceOf[Map[String, Structure]]
subColsDesc.values ++ subStructuresDesc.values.flatMap(getStructureSourceNames(_))
}
我想传递一个 (String -> String) 的递归映射,ia。结构的一个例子是:
Map("test" -> Map(
"newid" -> "id",
"newstring" -> "string",
"toto" -> Map("newdouble" -> "double")
),
"otherid" -> "id")
方法 getStructureSourceNames
应该 return "final" 值的列表,ia。浏览整棵树并为每个叶子获取字符串值。
当我 运行 这段代码时,这驱使我:
Warning:(78, 32) non-variable type argument String in type scala.collection.immutable.Map[String,Structure] (the underlying of Map[String,Structure]) is unchecked since it is eliminated by erasure
.filter(_._2.isInstanceOf[Map[String, Structure]])
另外,我不喜欢用isInstanceOf / asInstanceOf。通过谷歌搜索,我发现我可以使用模式匹配来检查类型,并获得具有预期类型的地图,但我找不到如何去做。
你有这样的代码示例吗?
有两种模式匹配:
1) sealed trait
上的模式匹配(好)
2) 模式匹配,其中模式涉及与任意匹配 类 和相等性检查(不优于 instanceOf
检查)
为了避免2)
你需要让你想要的类型匹配一个密封的特征:
sealed trait ConfigValue
case class StringValue(v: String) extends ConfigValue
case class MapValue(map: Map[String, ConfigValue]) extends ConfigValue
val struct: ConfigValue = MapValue(Map("key1" -> StringValue("v1"),
"key2" -> MapValue(Map("sub" -> StringValue("val")))))
def allValues(s: ConfigValue): Iterable[String] = {
s match {
case StringValue(v) => Seq(v)
case MapValue(map) => map.values.flatMap(v => allValues(v))
}
}
println(allValues(struct))
顺便说一下,您的结构看起来类似于 json。也许你可以重用一些 json 库。
来自以下代码:
type Structure = Map[String, Any]
def getStructureSourceNames(structuresDesc: Structure): Iterable[String] = {
val subColsDesc: Map[String, String] =
structuresDesc.filter(_._2.isInstanceOf[String]).asInstanceOf[Map[String, String]]
val subStructuresDesc: Map[String, Structure] = structuresDesc
.filter(_._2.isInstanceOf[Map[String, Structure]])
.asInstanceOf[Map[String, Structure]]
subColsDesc.values ++ subStructuresDesc.values.flatMap(getStructureSourceNames(_))
}
我想传递一个 (String -> String) 的递归映射,ia。结构的一个例子是:
Map("test" -> Map(
"newid" -> "id",
"newstring" -> "string",
"toto" -> Map("newdouble" -> "double")
),
"otherid" -> "id")
方法 getStructureSourceNames
应该 return "final" 值的列表,ia。浏览整棵树并为每个叶子获取字符串值。
当我 运行 这段代码时,这驱使我:
Warning:(78, 32) non-variable type argument String in type scala.collection.immutable.Map[String,Structure] (the underlying of Map[String,Structure]) is unchecked since it is eliminated by erasure
.filter(_._2.isInstanceOf[Map[String, Structure]])
另外,我不喜欢用isInstanceOf / asInstanceOf。通过谷歌搜索,我发现我可以使用模式匹配来检查类型,并获得具有预期类型的地图,但我找不到如何去做。
你有这样的代码示例吗?
有两种模式匹配:
1) sealed trait
上的模式匹配(好)
2) 模式匹配,其中模式涉及与任意匹配 类 和相等性检查(不优于 instanceOf
检查)
为了避免2)
你需要让你想要的类型匹配一个密封的特征:
sealed trait ConfigValue
case class StringValue(v: String) extends ConfigValue
case class MapValue(map: Map[String, ConfigValue]) extends ConfigValue
val struct: ConfigValue = MapValue(Map("key1" -> StringValue("v1"),
"key2" -> MapValue(Map("sub" -> StringValue("val")))))
def allValues(s: ConfigValue): Iterable[String] = {
s match {
case StringValue(v) => Seq(v)
case MapValue(map) => map.values.flatMap(v => allValues(v))
}
}
println(allValues(struct))
顺便说一下,您的结构看起来类似于 json。也许你可以重用一些 json 库。