1、map&flatMap
要输入的源文件word.txt如下
spark hbase
slor
hive kylin flink
map(func)
map函数会对每一条输入进行指定的操作,然后为每一条输入返回一个对象;map返回的数据对象的个数和原来的输入数据是相同的
val lineRdd = sc.textFile("./word.txt");
val mapRdd=lineRdd.map(f=>f.split("\\s")).foreach(x => println(x.toList));
返回的是Array[String]的RDD
List(spark, hbase)
List(slor)
List(hive, kylin, flink)
flatMap(func)
flatMap函数则是两个操作的集合——正是“先映射后扁平化”:同map函数一样:对每一条输入进行指定的操作,然后为每一条输入返回一个对象;最后将所有对象合并为一个对象;flatMap返回的个数则是不同的
val lineRdd = sc.textFile("./word.txt");
val mapRdd2=lineRdd.flatMap(f=>f.split("\\s+")).collect();
println(mapRdd2.toList)
返回的是String类型的RDD
List(spark, hbase, slor, hive, kylin, flink)
flatMap结合了map和flatten的功能,相当于如下操作
val mapRdd=lineRdd.map(f=>f.split("\\s+")).collect()
println("--------map--------")
mapRdd.foreach(f=>println(f.toList))
println("--------flat--------")
println(mapRdd.flatten.toList)
输出如下
--------map--------
List(spark, hbase)
List(slor)
List(hive, kylin, flink)
--------flat--------
List(spark, hbase, slor, hive, kylin, flink)
2、map&mapPartitions
两者操作粒度不同:map是对rdd中的每一个元素进行操作;mapPartitions则是对rdd中的每个分区的迭代器进行操作
假设一个rdd有6个元素,分成2个分区。如果使用map方法,map中的输入函数会被调用6次;而使用mapPartitions方法的话,其输入函数会只会被调用2次,每个分区调用1次。
val paralleRdd = sc.parallelize(1 to 6,2)
def funcPerElement(e:Int):Int = {
println("e="+e)
e*2
}
def funcPerPartition ( iter : Iterator [Int] ) : Iterator [Int] = {
println("iter="+iter)
var res = for (e <- iter ) yield e
res
}
paralleRdd.map(funcPerElement).collect()
paralleRdd.mapPartitions(funcPerPartition).collect()
map--e=1
map--e=2
map--e=3
map--e=4
map--e=5
map--e=6
mapPartitions--iter=non-empty iterator
mapPartitions--iter=non-empty iterator
两者初始化连接次数不同:在上面的例子中,mapPartitons只需初始化2个次,每个分区一次;而map要初始化6次,每个元素一次。显然在大量数据下mapPartitons的开销小,节省集群资源,便于进行批处理操作。
3、reduce&reduceByKey
reduce(func)
reduce 是一种聚合函数,接收两个参数,并返回一个参数,循环操作,直到最后剩下一个参数。用于数据交换和结合,聚合数据集与一体。
val paralleRdd = sc.parallelize(1 to 10)
val sum=paralleRdd.reduce((x, y) => x + y)
println(sum)
55
reduceByKey(func)
对一对(k,v)类型的数据集调用时,返回一个(k,v)对的数据集。对每个k的v用给定的reduce函数func聚合,该函数的类型必须为(v,v)=>v,对k相同的v操作得到新v。也即k相同的多个元素的v被reduce为一个值,然后与原RDD中的k组成一个新的kv对。如下示例:
val paralleRdd = sc.parallelize(List((1,2),(1,3),(2,5),(2,6),(3,7)))
val reduceRdd = paralleRdd.reduceByKey((x,y) => x + y).collect()
println(reduceRdd.toList)
对k相同的v进行累加操作, 得到新的k,v
List((1,5), (3,7), (2,11))
参考:http://spark.apache.org/docs/2.2.2/rdd-programming-guide.html#working-with-key-value-pairs