Scala嵌套HashMaps,如何访问Case Class值属性?

时间:2017-05-25 04:52:06

标签: scala hashmap case-class

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中获取值和属性。

5 个答案:

答案 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())中所示。