Scala新手,继续努力解决Option
相关代码问题。我有一个由Case Class实例构建的HashMap,它们本身包含带有Case Class实例值的哈希映射。我不清楚如何访问检索到的Class实例的属性:
import collection.mutable.HashMap
case class InnerClass(name: String, age: Int)
case class OuterClass(name: String, nestedMap: HashMap[String, InnerClass])
// Load some data...hash maps are mutable
val innerMap = new HashMap[String, InnerClass]()
innerMap += ("aaa" -> InnerClass("xyz", 0))
val outerMap = new HashMap[String, OuterClass]()
outerMap += ("AAA" -> OuterClass("XYZ", innerMap))
// Try to retrieve data
val outerMapTest = outerMap.getOrElse("AAA", None)
val nestedMap = outerMapTest.nestedMap
这会产生error: value nestedMap is not a member of Option[ScalaFiddle.OuterClass]
// Try to retrieve data a different way
val outerMapTest = outerMap.getOrElse("AAA", None)
val nestedMap = outerMapTest.nestedMap
这会产生error: value nestedMap is not a member of Product with Serializable
请告知我如何访问outerMapTest.nestedMap
。我最终还需要从nestedMap
HashMap中获取值和属性。
答案 0 :(得分:1)
由于您使用的是.getOrElse("someKey", None)
,因此会返回Product
类型(不是您期望的实际类型OuterClass
)
scala> val outerMapTest = outerMap.getOrElse("AAA", None)
outerMapTest: Product with Serializable = OuterClass(XYZ,Map(aaa -> InnerClass(xyz,0)))
所以Product
需要进行模式匹配或投放到OuterClass
模式匹配示例
scala> outerMapTest match { case x : OuterClass => println(x.nestedMap); case _ => println("is not outerclass") }
Map(aaa -> InnerClass(xyz,0))
当outerMapTest为None
时,铸造示例这是一个可怕的想法,(模式匹配比铸造更受青睐)
scala> outerMapTest.asInstanceOf[OuterClass].nestedMap
res30: scala.collection.mutable.HashMap[String,InnerClass] = Map(aaa -> InnerClass(xyz,0))
但更好的解决方法就是使用.get
,这非常聪明并且会为您提供Option[OuterClass]
,
scala> outerMap.get("AAA").map(outerClass => outerClass.nestedMap)
res27: Option[scala.collection.mutable.HashMap[String,InnerClass]] = Some(Map(aaa -> InnerClass(xyz,0)))
对于不存在的密钥,为您提供None
scala> outerMap.get("I dont exist").map(outerClass => outerClass.nestedMap)
res28: Option[scala.collection.mutable.HashMap[String,InnerClass]] = None
答案 1 :(得分:1)
您可以采取以下步骤深入了解嵌套结构。
outerMap.lift("AAA") // Option[OuterClass]
.map(_.nestedMap) // Option[HashMap[String,InnerClass]]
.flatMap(_.lift("aaa")) // Option[InnerClass]
.map(_.name) // Option[String]
.getOrElse("no name") // String
请注意,如果内部或外部地图中的任何一个没有指定的键(分别为“aaa”或“AAA”),那么整个事物将安全地产生默认字符串(“无名称”)。
答案 2 :(得分:1)
如果找不到HashMap
,则None
将返回key
,因此如果找不到密钥则无需getOrElse
返回None
解决您问题的一个简单方法是使用get only,如下所示
将您的第一个get
更改为
val outerMapTest = outerMap.get("AAA").get
您可以将输出检查为
println(outerMapTest.name)
println(outerMapTest.nestedMap)
将第二个get
更改为
val nestedMap = outerMapTest.nestedMap.get("aaa").get
您可以将输出测试为
println(nestedMap.name)
println(nestedMap.age)
希望这是有帮助的
答案 3 :(得分:0)
你想要
val maybeInner = outerMap.get("AAA").flatMap(_.nestedMap.get("aaa"))
val maybeName = maybeInner.map(_.name)
如果您喜欢冒险,可以使用
val name: String = maybeName.get
但如果不存在,那将会引发错误。如果是None
答案 4 :(得分:0)
您可以使用下面的表达式访问nestMap。
scala> outerMap.get("AAA").map(_.nestedMap).getOrElse(HashMap())
res5: scala.collection.mutable.HashMap[String,InnerClass] = Map(aaa -> InnerClass(xyz,0))
如果在outerMap Map对象中不存在"AAA"
,那么下面的表达式将返回一个空的HashMap,如.getOrElse
方法参数(HashMap()
)中所示。