前言
记录在学习大数据技术过程中的学习笔记
目录
Spark RDD 创建操作
val data = Array(1,2,3,4,5,6,7,8)
val distData = sc.parallelize(data,3)
外部数据源来创建
//本地当前目录下文件
val distFile1 = sc.textFile("data.txt")
//HDFS文件
val distFile2 = sc.textFile("hdfs://192.168.10.100/input/data.txt")
//本地指定目录下文件
val distFile3 = sc.textFile("file:/input/data.txt")
//本地指定目录下文件
val distFile4 = sc.textFile("/input/data.txt")
注意:textFile可以读取多个文件,或者一个文件夹,也支持压缩文件、包含通配符的路径
//读取多个文件
textFile("/input/001.txt,/input/002.txt")
//读取目录
textFile("/input")
//含通配符的路径
textFile("/input/*.txt")
//读取压缩文件
textFile("/input/*.gz")
Spark RDD 转换操作
map
map是对RDD中的每个元素都执行一个指定的函数来产生新的RDD;RDD之间的元素是一对一关系;
val conf = new SparkConf().setAppName("rdd_1").setMaster("local")
val sc = new SparkContext(conf)
sc.parallelize(1 to 10) //创建rdd(1~10)
.map(_*2) //对rdd中的每个元素 * 2
.foreach(println) //打印rdd中的所有元素
----------结果----------
2
4
6
8
10
12
14
16
18
20
-------------------------
filter
Filter是对RDD元素进行过滤;返回一个新的数据集,是经过func函数后返回为true的原元素组成
sc.parallelize(1 to 10) 创建rdd(1~10)
.filter(_ > 5) 过滤掉小于5的rdd元素
.foreach(println) 打印rdd中所有元素
---------------结果---------------
6
7
8
9
10
----------------------------------
flatMap
flatMap类似于map,但是每一个输入元素,会被映射到多个输出元素(因此,func函数的返回值是一个Seq),而不是单一的元素,rdd之间的元素是一对多的关系
也就是说进去一个元素,可以出来多个元素
sc.parallelize(1 to 2) //创建rdd(1~2)
.flatMap(_ to 2) //对每个进入的rdd元素,返回 自己 到 2 的数组
.foreach(println) //打印所有元素
-----------结果----------
1
2
2
-------------------------
mapPartitions
mapPartitions是map的一个变种。map的输入函数是应用于RDD中每个元素,而mapPartitions的输入函数是每个分区的数据,也就是把每个分区中的内容作为整体来处理
mapPartitionsWithIndex
mapPartitionsWithSpilt与mapPartitions的功能类似,只是多传入split index而已,所有func函数是(Int,Iterator<T>)=> Iterator<U>类型
sample
sample(withReplacement,fraction,seed)是根据给定的随机种子seed,随机抽样出frac的数据。withReplacement:是否放回抽样;
fraction:比例,0.1表示10%
sc.parallelize(1 to 100) //创建rdd(1~100)
.sample(false, 0.1, 0) //抽样10%,种子号 0
.foreach(println) //打印所有rdd
----------------结果----------------
10
39
41
53
54
58
60
80
89
98
-------------------------------------
union
union(otherDataset)是数据合并,返回一个新的数据集,由原数据集和otherDataset联合而成
sc.parallelize(1 to 5) //创建rdd1(1~5)
.union( //联合
sc.parallelize(6 to 10 //创建rdd2(6~10)
))
.foreach(println) //打印
--------------------结果--------------------
1
2
3
4
5
6
7
8
9
10
---------------------------------------------
groupByKey
groupByKey([numTasks])是数据分组操作,在一个由(k,v)对组成的数据集上调用,返回一个(K,Seq[V])对的数据集。
val rdd = sc
.parallelize(Array("小明" -> "age:20" ,"小明" -> "语文:60","小明" -> "数学:70","小明" -> "英语:85")) //创建rdd (k,v) 键值对
rdd.groupByKey() //根据k(小明)分组
.foreach(line => { //遍历rdd
println(line._1) //打印k
println(line._2) //打印v
})
-----------------------结果-----------------------
小明
CompactBuffer(age:20, 语文:60, 数学:70, 英语:85)
--------------------------------------------------
reduceByKey
reduceByKey(func,[numTasks])是数据分组聚合操作,在一个(k,v)对的数据集上使用,返回一个(k,v)对的数据集,key相同的值,都被使用指定的reduce函数聚合到一起
sc.parallelize(Array("k" -> 1,"k" -> 2,"k1" -> 2,"k1" -> 3)) //创建rdd(k,v)键值对
.reduceByKey(_+_) //对相同的k进行聚合,对相同的k进行求和
.foreach(line => { //遍历
println(line._1,line._2) //打印(k,v)键值对
})
------------------结果-------------------
(k,3)
(k1,5)
-----------------------------------------
aggregateByKey
aggreateByKey(zeroValue:U)(seqOp:(U,T)) => U,combOp:(U,U) => U) 和 reduceByKey的不同在于,reduceByKey输入输出都是(K,V),而aggreateByKey输出是(K,U),可以不同于输入(K,V),aggreateByKey的三个参数:
zeroValue:U ,初始值,比如空列表
seqOp:(U,T) => U,seq操作符,描述如何将T合并入U,比如如何将item合并到列表;
combOp:(U,U) => U,comb操作符,描述如何合并两个U,比如合并连个列表;
所以aggreateByKey可以看成更高抽象的,更灵活的reduce或group。
combineByKey
combineByKey是对RDD中的数据集按照Key进行聚合操作。聚合操作的逻辑通过自定义函数提供combineByKey。
combineByKey[C](createCombiner:(V)) => C,mergeValue:(C,V) => C,mergeCombiner:(C,C)
=> C,numPartitions:Int):RDD[(K,C)]类型的RDD转换为(K,C)类型的RDD,C和V可以不一样。
sortByKey
sortBykey([ascending],[numTasks])是排序操作,对(k,v)类型的数据按照K进行排序,其中K需要实现Ordered方法
sc.parallelize(Array(3 -> "v",2 -> "v",4 -> "v",1 -> "v"))
.sortByKey() //按k排序
.foreach(println)
----------------结果------------------
(1,v)
(2,v)
(3,v)
(4,v)
--------------------------------------
join
join(otherDataset,[numTasks])是连接操作,根据k连接两个rdd
val rdd1 = sc.parallelize(Array(("k",1),("k1",2)))
val rdd2 = sc.parallelize(Array(("k",3),("k1",4)))
rdd1
.join(rdd2) //连接两个rdd
.foreach(println)
-----------------结果-------------------
(k,(1,3))
(k1,(2,4))
----------------------------------------
Spark RDD 行动操作
rduce
reduce(func)是对数据集的所有元素执行聚集(func)函数,该函数必须是可交换的。
println(
sc.parallelize(1 to 10)
.reduce(_+_) //聚合操作,求和
)
----------------结果---------------
55
-----------------------------------
collect
collect是将数据集的所有元素以一个array的形式返回
sc.parallelize(1 to 5)
.collect() //返回一个数组
.foreach(println(_))
---------------结果-------------
1
2
3
4
5
--------------------------------
count
count 统计rdd元素中的个数
val value = sc.parallelize(Array(1,2,3))
println(
value
.count() //统计个数
)
----------------结果----------
3
------------------------------
first
返回rdd中第一个元素
println(
sc.parallelize(Array(1,2,3,4,5))
.first() // 返回rdd 中的第一个元素
)
-------------结果--------------
1
-------------------------------
take
返回前n个元素
sc.parallelize(Array(1,2,3,4,5,6))
.take(3) //返回前n个元素
.foreach(println)
----------------结果----------------
1
2
3
-----------------------------------
takeSample
返回包含随机的num个元素的数组,和Sample不同,takeSample是行动操作,所以返回的是数组而不是RDD,其中第一个参数withReplacement是抽样时是否放回,第二个参数num会精确指定抽样数,而不是比例。
sc.parallelize(1 to 10)
.takeSample(true,5) //开启随机抽样,抽取5个
.foreach(println)
-------------结果------------
4
7
4
3
6
-----------------------------
takeOrdered
返回包含随机的n个元素的数组,按照顺序输出
sc.parallelize(1 to 10)
.takeOrdered(5) //随机抽取5个
.foreach(println)
--------------结果-------------
1
2
3
4
5
-------------------------------
saveAsTextFile
把数据集中的元素写到一个文本文件,Spark会对每个元素调用toString方法来把每个元素存成文本文件的一行
countByKey
对于(K,V)类型的RDD,返回一个(K,Int)的map,Int为K的个数
foreach
foreach(func)时数据集中的每个元素都执行func函数