类型化的Scala对象如何丢失其类型?
在下面的代码段中,类型化的Scala对象如何丢失其类型?,scala,Scala,在下面的代码段中,entities是一个Map[String,Seq[String]]对象,我从其他代码段接收到它。目标是将实体对象映射到两列Spark数据帧中;但是,在我到达那里之前,我发现了一些非常不寻常的结果 val data: Map[String, Seq[String]] = Map("idtag" -> Seq("things", "associated", "with", "id")) println(data) println(data.toSeq) data.toSe
entities
是一个Map[String,Seq[String]]
对象,我从其他代码段接收到它。目标是将实体对象映射到两列Spark数据帧中;但是,在我到达那里之前,我发现了一些非常不寻常的结果
val data: Map[String, Seq[String]] = Map("idtag" -> Seq("things", "associated", "with", "id"))
println(data)
println(data.toSeq)
data.toSeq.foreach{println}
data.toSeq.map{case(id: String, names: Seq[String]) => names}.foreach{println}
val eSeq: Seq[(String, Seq[String])] = entities.toSeq
println(eSeq.head)
println(eSeq.head.getClass)
println(eSeq.head._1.getClass)
println(eSeq.head._2.getClass)
eSeq.map{case(id: String, names: Seq[String]) => names}.foreach{println}
控制台上的上述输出为:
Map(idtag -> List(things, associated, with, id))
ArrayBuffer((idtag,List(things, associated, with, id)))
(idtag,List(things, associated, with, id))
List(things, associated, with, id)
(0CY4NZ-E,["MEC", "Marriott-MEC", "Media IQ - Kimberly Clark c/o Mindshare", "Mindshare", "WPP", "WPP Plc", "Wavemaker Global", "Wavemaker Global Ltd"])
class scala.Tuple2
class java.lang.String
class java.lang.String
Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to scala.collection.Seq
at package.EntityList$$anonfun$toStorage$4.apply(EntityList.scala:31)
我硬编码的数据
对象按预期运行。实体映射上的.toSeq
函数生成元组的Seq
(作为ArrayBuffer实现);这些元组可以通过映射进行处理
但是使用实体
对象,您可以看到,当我使用.head
获取第一个元素时,它是一个Tuple2[String,String]
。这怎么可能发生呢?元组的第二个元素如何变成字符串并导致异常
如果最后一行被更改为反映Tuple2[String,String]
,我会更加困惑:
eSeq.map{case(id: String, names: String) => names}.foreach{println}
然后我们得到一个编译错误:
/path/to/repo/src/main/scala/package/EntityList.scala:31: error: pattern type is incompatible with expected type;
found : String
required: Seq[String]
eSeq.map{case(id: String, names: String) => names}.foreach{println}
我不能用我自己创建的
Map[String,Seq[String]]
复制这种奇怪的行为,正如您在这段代码中看到的那样。有人能解释这种行为及其发生的原因吗?问题似乎是实体。toSeq
在返回的数据类型上撒谎,所以我会查看“其他代码”并检查它是否做了正确的事情
具体来说,它声明返回Seq[(String,Seq[String])]
,编译器相信它。但是getClass
显示元组中的第二个对象实际上是java.lang.String
而不是Seq[String]
如果这是正确的,match
语句将使用unapply
提取值,然后在尝试将名称
转换为所述类型时出错
我注意到该字符串似乎是一个包含在
[
]
中的字符串列表,因此似乎任何创建实体的东西都无法将其解析为序列,而是声称它成功了。什么是实体???您将其声明为Seq[(String,Seq[String])]
,但显然不是这样。编译错误是预期的:您将其声明为Seq
,然后尝试以字符串的形式访问@Dima Entities不是我创建的。它的类型在第一句中给出。注意我通过.toSeq
命令转换它的位置,以及分配给结果val eSeq
的类型。编译错误当然是预期的,但第一个异常不是。请仔细阅读问题。我注意到println(data.toSeq.head)
的输出和println(eSeq.head)
的输出看起来不像是相关的数据格式。[
和]
从哪里来?一个在数据中有引号,“
,但另一个没有。实体
看起来或行为不像Scala创建的映射[String,Seq[String]]
@jwvh我从另一个Scala软件中获得了实体
;但我相信它的大部分起源是Java。我假设它是一个Java数组,但这似乎不正确。你已经触及了问题的核心,我不明白发生了什么。我为eSeq
添加了一个特定类型,但这似乎没有帮助@问题是“第一句中给出的类型”是错误的。这就是为什么你会得到例外。我读得很透彻。请不要告诉我该怎么做。