我正在使用Spark 1.1.0和Scala 2.10.4。
我有如下输入:
100,aviral,Delhi,200,desh
200,ashu,hyd,300,desh
执行时:
sc.textFile(inputFile).keyBy(line => line.split(',')(2))
Spark给了我ArrayOutOfBoundsException
。为什么呢?
请注意,相同的代码在Spark 1.4.0中运行良好。任何人都可以解释不同行为的原因吗?
答案 0 :(得分:1)
定义带有一些数据的rdd
val rdd = sc.parallelize(Array("1,abc,2,xyz,3","4,qwerty,5,abc,4","9,fee,11,fie,13"))
rdd: org.apache.spark.rdd.RDD[String] = ParallelCollectionRDD[0] at parallelize at <console>:21
通过.keyBy()
rdd.keyBy( line => (line.split(','))(2) ).collect()
res4: Array[(String, String)] = Array((2,1,abc,2,xyz,3), (5,4,qwerty,5,abc,4), (11,9,fee,11,fie,13))
请注意,它在分割后从第3个元素生成键,但打印看起来很奇怪。起初它看起来不正确,但事实证明这是一个打印工件,因为它缺少字符串上的任何引号。我们可以对此进行测试以选择值,看看我们是否得到了回线:
rdd.keyBy(line => line.split(',')(2) ).values.collect()
res12: Array[String] = Array(1,abc,2,xyz,3, 4,qwerty,5,abc,4, 9,fee,11,fie,13)
这看起来像预期的那样。请注意,数组中只有3个元素,这里的逗号位于元素字符串中。
我们也可以使用.map()
进行配对,如下所示:
rdd.map( line => (line.split(',')(2), line.split(',')) ).collect()
res7: Array[(String, Array[String])] = Array((2,Array(1, abc, 2, xyz, 3)), (5,Array(4, qwerty, 5, abc, 4)), (11,Array(9, fee, 11, fie, 13)))
打印为元组......
或者为了避免重复工作,可能:
def splitter(s:String):(String,Array[String]) = {
val parsed = s.split(',')
(parsed(2), parsed)
}
rdd.map(splitter).collect()
res8: Array[(String, Array[String])] = Array((2,Array(1, abc, 2, xyz, 3)), (5,Array(4, qwerty, 5, abc, 4)), (11,Array(9, fee, 11, fie, 13))
这有点容易阅读。它也稍微解析了一下,因为在这里我们将线分成了单独的值。
答案 1 :(得分:1)
问题是你在第一行之后有一个空行 - 拆分它不会返回包含必要列数的数组。
1,abc,2,xyz,3
<empty line - here lies the problem>
4,qwerty,5,abc,4
删除空行。
另一种可能性是其中一行没有足够的列。您可以过滤所有不具有所需列数的行(但请注意可能的数据丢失)。
sc.textFile(inputFile)
.map.(_.split(","))
.filter(_.size == EXPECTED_COLS_NUMBER)
.keyBy(line => line(2))