spark RDD编程 第1关:数据去重

Spark RDD编程初级实践(一)

任务描述

本关任务:编写Spark独立应用程序实现数据去重。
相关知识

为了完成本关任务,你需要掌握:RDD的创建;RDD的转换操作;RDD的行动操作。
RDD的创建

使用textFile()方法从本地文件系统中加载数据创建RDD,示例如下:

    val lines = sc.textFile("file:///home/hadoop/word.txt")

执行sc.textFile()方法以后,Spark从本地文件word.txt中加载数据到内存,在内存中生成一个RDD对象lines,这个RDD里面包含了若干个元素,每个元素的类型是String类型,也就是说,从word.txt文件中读取出来的每一行文本内容,都成为RDD中的一个元素。

使用map()函数转换得到相应的键值对RDD,示例如下:

    val lines = sc.textFile("file:///home/hadoop/word.txt")
    val pairRDD = lines.flatMap(line => line.split(" ")).map(word => (word,1))

上面示例中,map(word=>(word,1))函数的作用是取出RDD中的每个元素,也就是每个单词,赋值给word,然后把word转换成 (word,1) 的键值对形式。

RDD的转换操作

对于RDD而言,每一次转换操作都会产生新的RDD,供给下一个操作使用。RDD的转换过程是惰性求值的,也就是说,整个转换过程只是记录了转换的轨迹,并不会发生真正的计算,只有遇到行动操作时,才会触发真正的计算。常见的RDD转换操作如下所示:

**filter(func)**:筛选出满足函数func的元素,并返回一个新的RDD,示例如下:

    val lines = sc.textFile("file:///home/hadoop/word.txt")
    val linesWithSpark = lines.filter(line => line.contains("Spark"))

**map(func)**:将每个元素传递到函数func中,并将结果返回为一个新的RDD,示例如下:

    val lines = sc.textFile("file:///home/hadoop/word.txt")
    val words = lines.map(line => line.split(" "))

**groupByKey()**:应用于(K,V)键值对RDD时,返回一个新的(K, Iterable)形式的RDD,示例如下:

    val lines = sc.textFile("file:///home/hadoop/word.txt")
    val words = lines.flatMap(line => line.split(" ")).map(word => (word,1)).groupByKey()

**sortByKey()**:应用于(K,V)键值对RDD时,返回一个新的根据key排序的RDD,示例如下:

    val pairRDD = sc.parallelize(Array("Hadoop",3),("Spark",5),("Hive",2))
    pairRDD.sortByKey().foreach(println)

输出:
(Hadoop,3)
(Hive,2)
(Spark,5)

**partitionBy(partitioner: Partitioner)**:根据partitioner函数生成新的ShuffleRDD,将原RDD重新分区,示例如下:

    val lines = sc.textFile("file:///home/hadoop/word.txt", 3)
    val words = lines.flatMap(line => line.split(" ")).map(word => (word,1)).partitionBy(new HashPartitioner(1))

keys:将键值对RDD中所有元素的key返回,形成一个新的RDD,示例如下:

    val pairRDD = sc.parallelize(Array("Hadoop",3),("Spark",5),("Hive",2))
    pairRDD.keys.foreach(println)

输出:
Hadoop
Spark
Hive

RDD的行动操作

对于RDD而言,只有遇到行动操作时才会执行“从头到尾”的真正的计算,从文件中加载数据,完成一次又一次转换操作,最终,完成行动操作得到结果。常见的RDD行动操作如下所示:

**count()**:返回RDD中元素的个数
**collect()**:以数组的形式返回RDD中的所有元素
**first()**:返回RDD中的第一个元素
**take(n)**:以数组的形式返回RDD中的前n个元素
**reduce(func)**:通过函数func(输入两个参数并返回一个值)聚合RDD中的元素
**foreach(func)**:将RDD中的每个元素传递到函数func中运行 下面通过一个示例来介绍上述行动操作,如下所示:

    val rdd = sc.parallelize(Array(1,2,3,4,5))
    println(rdd.count)
    println(rdd.first)
    println(rdd.take(3).mkString(", "))
    println(rdd.collect().mkString("-> "))
    rdd.foreach(println)

输出: 5 1 1, 2, 3 1-> 2-> 3-> 4-> 5 1 2 3 4 5

编程要求

对于两个输入文件A和B,编写Spark独立应用程序,对两个文件进行合并、剔除其中重复的内容并排序,得到一个新文件C。下面是输入文件和输出文件的一个样例,供参考。
输入文件A的样例如下:
20170101 x
20170102 y
20170103 x
20170104 y
20170105 z
20170106 z
输入文件B的样例如下:
20170101 y
20170102 y
20170103 x
20170104 z
20170105 y
输出文件C的样例如下:
20170101 x
20170101 y
20170102 y
20170103 x
20170104 y
20170104 z
20170105 y
20170105 z
20170106 z
测试说明

本实训目前是基于Spark单机模式的运行方式,完成整个评测流程所需时间较长(全过程耗时约60秒),请耐心等待!

开始你的任务吧,祝你成功!

代码

import org.apache.spark.SparkContext
import org.apache.spark.SparkConf
import org.apache.spark.HashPartitioner
object RemDup {
  def main(args: Array[String]): Unit = {
    val conf = new SparkConf().setAppName("RemDup").setMaster("local")
    val sc = new SparkContext(conf)
    //输入文件fileA.txt和fileB.txt已保存在本地文件系统/root/step1_files目录中
    val dataFile = "file:///root/step1_files"
    val data = sc.textFile(dataFile, 2)
    /********** Begin **********/
    //第一步:执行过滤操作,把空行丢弃。
    val rdd1 = data.filter(_.trim().length > 0)
    //第二步:执行map操作,取出RDD中每个元素,去除尾部空格并生成一个(key, value)键值对。
    val rdd2 = rdd1.map(line => (line.trim, ""))
    //第三步:执行groupByKey操作,把所有key相同的value都组织成一个value-list。
    val rdd3 = rdd2.groupByKey()
    //第四步:对RDD进行重新分区,变成一个分区,
    //在分布式环境下只有把所有分区合并成一个分区,才能让所有元素排序后总体有序。
    val rdd4 = rdd3.partitionBy(new HashPartitioner(1))
    //第五步:执行sortByKey操作,对RDD中所有元素都按照key的升序排序。
    val rdd5 = rdd4.sortByKey()
    //第六步:执行keys操作,将键值对RDD中所有元素的key返回,形成一个新的RDD。
    val rdd6 = rdd5.keys
    //第七步:执行collect操作,以数组的形式返回RDD中所有元素。
    val rdd7 = rdd6.collect()
    //第八步:执行foreach操作,并使用println打印出数组中每个元素的值。
    println("") //注意:此行不要修改,否则会影响测试结果,在此行之后继续完成第八步的代码。
    rdd7.foreach(println)
    /********** End **********/
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值