为什么拆分字符串会在Spark 1.1.0中产生ArrayOutOfBoundsException(在1.4.0中正常工作)?

时间:2015-08-30 05:28:58

标签: scala apache-spark

我正在使用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中运行良好。任何人都可以解释不同行为的原因吗?

2 个答案:

答案 0 :(得分:1)

它在Spark 1.4.1 / spark-shell

中工作正常

定义带有一些数据的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))