Spark中Scala匿名函数内代码块的含义及示例解析
解答你的Scala匿名函数与Spark代码疑问
嘿,作为经常写Scala和Spark代码的开发者,我来帮你拆解这段代码,逐一解答你的疑问:
第一个问题:代码逻辑的理解是否正确?
你的理解完全没错!这段代码的执行流程就是你描述的那样:
- 对RDD中的每一个
WikipediaArticle对象,先筛选出该文章提到的语言(通过langs.filter(lang => article.mentionsLanguage(lang))) - 把每个匹配的语言和对应的文章组成元组
(lang, article),得到一个元组列表 flatMap操作会把所有这些列表扁平化——也就是把多个列表里的元组都拆出来,变成一个包含所有元组的RDD- 最后调用
groupByKey,将相同语言对应的所有WikipediaArticle聚合到一起,得到最终的RDD[(String, Iterable[WikipediaArticle])]
第二个问题:匿名函数的代码块是否可以写任意代码?
是的!Scala中用{}包裹的代码块,默认会把最后一行代码的执行结果作为整个代码块的返回值,只要这个返回值的类型符合上下文的要求(这里flatMap要求返回一个可遍历的集合,比如List、Seq等)。
你完全可以在代码块里写任意合法的Scala代码:比如定义临时变量、添加调试打印、做复杂的条件判断,甚至调用其他工具方法。举个例子,我们可以给代码加个临时变量和调试输出,依然是合法的:
rdd.flatMap(article => { // 定义临时变量存储匹配的语言 val matchedLangs = langs.filter(lang => article.mentionsLanguage(lang)) // 添加调试打印 println(s"当前文章提到的语言:${matchedLangs.mkString(",")}") // 最后一行返回元组列表,作为代码块的结果 matchedLangs.map(lang => (lang, article)) })
第三个问题:是否每个article都会遍历langs列表?
没错,这段代码里每处理一个WikipediaArticle对象,都会完整遍历一遍langs列表,对列表中的每个语言调用article.mentionsLanguage(lang)来判断是否匹配。
如果langs是一个很小的集合(比如只有几种主流语言),这种写法完全没问题;但如果langs非常大,可能会带来一定的性能开销——不过这是另一个优化层面的问题了,当前代码的逻辑确实是这样的。
内容的提问来源于stack exchange,提问作者Shengxin Huang
相关产品推荐
相关产品推荐

