Spark中的常用算子(map,mapPartitions,foreach,foreachPatition)
前言
map:用于遍历RDD,将函数应用于每一个元素,返回新的RDD(transformation算子)
foreach:用于遍历RDD,将函数应用于每一个元素,无返回值(action算子)
mapPatitions:用于遍历操作RDD中的每一个分区,返回生成一个新的RDD(transformation算子)
foreachPatition:用于遍历操作RDD中的每一个分区,无返回值(action算子)
总结:一般使用mapPatitions和foreachPatition算子比map和foreach更加高效,推荐使用。
RDD的操作
今天学习了一下Spark中的RDD的编程,熟悉了一下RDD常用的接口,看到网上有一道题,使用RDD的接口去实现了一下,RDD编程确实强大!
练习题目
如下:在(ip user)的键值对中(空格分隔),如
a.text
127.0.0.1 xiaozhang
127.0.0.1 xiaoli
127.0.0.2 wangwu
127.0.0.3 lisi
…..
B.text
127.0.0.4 lixiaolu
127.0.0.5 lisi
127.0.0.3 zhangsan
每个文件至少有1000万行,请用程序完成以下工作:
1.各个文件的ip数(涉及算子和RDD操作:map、collect)
val sc = new SparkContext(conf)
val rdd = sc.textFile("a.text").map {
line =>
val urls = line.split(" ")
urls(0)
}.collect()
2.出现在b.text而没有出现在a.text的IP(涉及算子和RDD操作:map、contains)
与第1个类似,通过spark的map算子将每一行分隔,先得到文件b.text中所有的IP,然后,
该题目解题思路和第一题类似,首先可以参考第1题的方法分别获取两个文件中的IP,然后我们可以利用RDD提供的filter和contains接口,过滤出满足出现在b.text而没有出现在a.text中的IP
val sc = new SparkContext(conf)
//a.text中的ip
val rdd1 = sc.textFile("a.text").map {
line =>
val urls = line.split(" ")
urls(0)
}.collect()
//b.text中的ip
val rdd2 = sc.textFile("b.text").map {
line =>
val urls = line.split(" ")
urls(0)
}.collect()
//出现在b.text而没有出现在a.text的IP
rdd2.filter {
line =>
!rdd1.contains(line)
}.foreach(println)
3.每个user出现的次数以及每个user对应的IP的个数 (涉及算子和RDD操作:map、union、reduceByKey)
1)每个user出现的次数
//a.text中每个user出现的次数
val rdd1 = sc.textFile("a.text").map {
line =>
val urls = line.split(" ")
urls(1)
}.map(word=>(word,1)).reduceByKey(_+_)
//b.text中每个user出现的次数
val rdd1 = sc.textFile("b.text").map {
line =>
val urls = line.split(" ")
urls(1)
}.map(word=>(word,1)).reduceByKey(_+_)
//两个文件中每个user出现的次数
val rdd3 = rdd1.union(rdd2).reduceByKey(_+_)
2)每个user对应的IP个数
val rdd1 = sc.textFile("a.text").map{
line =>
val user = line.split(" ")
user(1)
}.collect()
val rdd2 = sc.textFile("b.text").map{
line =>
val user = line.split(" ")
(user(1), user(0))
}
val rdd3 = sc.textFile("a.text").map{
line =>
val user = line.split(" ")
(user(1), user(0))
}
rdd3.union(rdd2).groupByKey().sortByKey().map{
row =>
val userNames = row._2.toArray
(row._1,(userNames.mkString(",")))
}.foreach{
row =>
println(row._1 + " " + row._2)
}
4.对应IP数最多的前K个user
该题与第3题是反向的,只需要先获取每个ip对应的用户,代码示例如下:
val rdd1 = sc.textFile("a.text").map{
line =>
val user = line.split(" ")
user(0)
}.collect()
val rdd2 = sc.textFile("b.text").map{
line =>
val user = line.split(" ")
(user(0), user(1))
}
val rdd3 = sc.textFile("a.text").map{
line =>
val user = line.split(" ")
(user(0), user(1))
}
rdd3.union(rdd2).groupByKey().sortByKey().map{
row =>
val userNames = row._2.toArray
(row._1,(userNames.mkString(",")))
}.foreach{
row =>
println(row._1 + " " + row._2)
}