spark RDD常用函数/操作
文中的代码均可以在spark-shell中运行。
transformations
map(func)
集合内的每个元素通过function映射为新元素
val a = Array(1,2,3,4)
val pa = sc.parallelize(a)
val resultRdd = pa.map( _ + 1)
注意对于所有transformation操作,生成的都是一个新的RDD(这里就是resultRdd),并不实际进行运算,只有对RDD进行action操作时才会实际计算并产生结果:
scala> resultRdd.collect
res3: Array[Int] = Array(2, 3, 4, 5)
以下的transformation操作同理。
filter(func)
通过func
过滤集合的元素,func
的返回值必须是Boolean
类型
val a = Array(1,2,3,4)
val pa = sc.parallelize(a)
val resultRdd = pa.filter( _ > 1)
scala> resultRdd.collect
res4: Array[Int] = Array(2, 3, 4)
flatmap(func)
通过func
将集合内的每一元素,映射为一个序列(具体的是TraversableOnce[?],这里可以不用管这个类型,spark会自己作隐式转换,一般的可以顺序迭代的序列都可以)。
说起来可能不好理解,举个例子。还是[1,2,3,4]
吧,假设func是这样的:x => Array(x+0.1, x+0.2)
,也就是返回一个序对,flatMap流程可以看作是先对每个元素执行func,得到
[(1.1, 1.2), (2.1, 2.2), (3.1, 3.2), (4.1, 4.2)]
最后将所有的序列展平,就得到:
[1.1, 1.2, 2.1, 2.2, 3.1, 3.2, 4.1, 4.2]
代码形式:
val a = Array(1,2,3,4)
val pa = sc.parallelize(a)
val resultRdd = pa.flatMap( x => Array(x+0.1,x+0.2) )
scala> resultRdd.collect
res8: Array[Double] = Array(1.1, 1.2, 2.1, 2.2, 3.1, 3.2, 4.1, 4.2)
mapPartitions(func)
和map类似,但它是在RDD的每个分区分别运行,可以理解成将一个分区内的元素映射成一个新分区,最后将所有新分区拼起来成为一个新RDD。
当对T
类型的RDD使用此函数时,func
的签名必须是Iterator<T> => Iterator<U>
val a = Array(1,2,3,4)
val pa = sc.parallelize(a)
val resultRdd = pa.mapPartitions(iter => iter.map(_+1)) // 不要将这里的iter.map和RDD的map弄混了,这是scala内置的针对集合的操作
scala> resultRdd.collect
res11: Array[Int] = Array(2, 3, 4, 5)
mapPartitionsWithIndex(func)
类似mapPartitions(func)
,但是多提供一个分区的索引号信息
所以对于元素为T
类型的RDD,func
的类型签名应该是(Int, Iterator<T>) => Iterator<U>
val a = Array(1,2,3,4)
val pa = sc.parallelize(a)
val resultRdd = pa.mapPartitionsWithIndex( (index, iter) => iter.map( x => (x,s"分区$index")) )
scala> resultRdd.collect
res14: Array[(Int, <