最近开始用scala做一些工作。
scala和java可以说同源同种,而我上一次写java程序可能要追溯到快十年前了。平常习惯使用弱类型语言,突然间切到scala,还有点不太适应。最近碰到的这个小问题,就耗费掉我不少时间。
大概场景是有两份数据left和right,需要对他们做一次全连接(fullOuterJoin),然后对于得到的结果,优先选择left中的数据,left中的数据不存在则选择right中的数据。示意如下:
1 | 复制代码scala> val left = sc.makeRDD(Seq(("1","2","LEFT12"),("2","3","LEFT23"))) |
接下进行fullOuterJoin,查看文档后得到,fullOuterJoin返回的结果是两个Option组成的元组。感谢scala的模式匹配,可以避免写一大堆if else,以下代码看上去很美好:
1 | 复制代码scala> val total = leftmap.fullOuterJoin(rightmap).map(kv => |
但是返回值java.io.Serializable是什么鬼?这类型和我后续要把数据落地的接口不匹配,后续工作无法进行啊。
翻看过各种Stack Overflow上的问答,各种java.io.serializable的搜索结果,最终才弄明白,原因是scala的模式匹配语句match的返回值类型是各个case字句返回值类型的最近公共父类。这里的问题就出在case _ => None这一句,None类型和s的类型,导致最终scala找到java.io.serializable。
再做个试验验证下,比如这样的模式匹配:
1 | 复制代码scala> val total = leftmap.fullOuterJoin(rightmap).map(kv => |
返回类型将是整型和字符串类型的公共父类Any类型:
1 | 复制代码total: org.apache.spark.rdd.RDD[Any] = MapPartitionsRDD[19] at map at <console>:32 |
解决方案也很简单,既然我知道我要的就是字符串,那么最后一个case子句返回空字符串:
1 | 复制代码scala> val total = leftmap.fullOuterJoin(rightmap).map(kv => |
对于scala/spark,我还是萌新一枚,有什么说的不准确的地方,也欢迎各位大佬留言批评指正~
推荐阅读:
Python协程:从yield/send到async/await/
打通Python和C++
待业青年
转载请注明出处: blog.guoyb.com/2017/12/09/…
欢迎使用微信扫描下方二维码,关注我的微信公众号TechTalking,技术·生活·思考:后端技术小黑屋
本文转载自: 掘金