Spark RDD 语法学习笔记

一、RDD的创建

1、从内存中创建-> rddBuilderMemory

sc.makeRDD(List(1,2,3,4,5))

2、从文件中创建->rddBuilderFile

val value2: RDD[String] = sparkContext.textFile("/**/**")
val value1: RDD[Nothing] = sparkContext.objectFile("/**/**")
val value: RDD[(String, Int)] = sparkContext.sequenceFile("/**/**")

二、RDD算子

RDD算子 = RDD方法:

1、转换 :功能的补充和封装,将旧的RDD包装成新的RDD

eg:flatMap、map

2、行动:触发任务的调度和作业的执行

eg:collect

RDD转换算子

单值类型
map
//此处函数作为参数
/*
map是一对一的转换操作
map算子是作用在每个分区、每个元素上,对每个元素执行自定义的函数
val rddMap: Array[Int] = rdd.collect().map((i: Int) => { i * 5})
*/

val rddMap = rdd.map(_ * 5)
rddMap.collect().foreach(println)
mapPartitions
val rdd: RDD[Int] = sparkContext.makeRDD(List(1, 2, 3, 4, 5, 6),2)
//mapPartitions,相当于把同一个分区的先执行
将待处理的数据
以分区为单位发送到计算节点进行处理,
这里的处理是指可以进行任意的处理,哪怕是过滤数据。
(效率较高,得到一个分区后的数据才开始计算,但是对内存需求较高)
val mapParRdd: RDD[Unit] = rdd.mapPartitions(
  _.map(println)//此时的参数为 迭代器 iter
)
mapParRdd.collect()
mapPartitionsWithIndex
带分区号的map,把iter进行更改,再返回
样例为输出带分区号的元素
val rdd = sparkContext.makeRDD(List(1, 2, 3, 4, 5, 6, 7, 8, 9))
rdd.mapPartitionsWithIndex(
f = (index, iter) => {
  iter.map((index,_))
}
).collect().foreach(println(_))
groupBy
/*
* 返回值为key,根据内层函数的返回值分组归类*/
println("奇偶数归类")
val rdd: RDD[Int] = sparkContext.makeRDD(List(1, 2, 3, 4, 5, 6, 7, 8, 9))
val groupByRdd: RDD[(Int, Iterable[Int])] = rdd.groupBy(_ % 2)
groupByRdd.collect().foreach(println)
println("根据字符串首字母归类")
val rdd1: RDD[String] = sparkContext.makeRDD(List("pokey", "hotpot", "login", "hello", "hello"))

rdd1.groupBy(_.charAt(0)).collect().foreach(println(_))
glom
/*
* 将同一个分区的数据转换为同类型的内存数组进行处理
*/
val rdd: RDD[Int] = sparkContext.makeRDD(List(1, 2, 3, 4, 5, 6, 7, 8, 9))
val glomRdd: RDD[Array[Int]] = rdd.glom()//Int->Array[Int]
glomRdd.collect().foreach(data=>println(data.mkString(",")))
flatMap
/*
  flatMap就是扁平化处理
*/
val rddStr: RDD[String] = sparkContext.makeRDD(List("hello hotpot", "hello pokey", "hello login"))
println("\neg No2 按空格分隔")

val flatRddStr: RDD[String] = rddStr.flatMap(_.split(" "))
flatRddStr.collect().foreach(println(_))
filter 
/*
* filter 就是过滤器,将数据根据指定的规则筛选符合的数据保留
  自定义函数用于定义过滤规则
* */
val rdd: RDD[Int] = sparkContext.makeRDD(List(1, 23, 456, 789, 456, 123, 4, 5, 0, 9, 132, 96874, 132, 898, 9, 4, 65497, 43))
val filterRdd: RDD[Int] = rdd.filter(_ >= 12)
filterRdd.collect().foreach(println(_))
sample
//sample的三个参数
withReplacement: Boolean,#是否又放回抽样
fraction: Double,#抽取的几率
seed: Long = Utils.random.nextLong#随机数种子
val rdd: RDD[Int] = sparkContext.makeRDD(List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
rdd.sample(true,0.4).collect().foreach(println(_))
distinct

对元素进行去重,去重原理:

去重的方式是通过将数值map成键值对的形式然后通过reducebykey聚合,最后选出聚合结果。

a->(a,1),通过reducebukey聚合

val rdd: RDD[Int] = sparkContext.makeRDD(List(1, 1, 2, 132, 456, 15, 489, 12, 12, 12, 12, 12, 12, 12))
rdd.distinct().sortBy(data=>data).collect().foreach(println(_))
coalesce

根据数据量缩减分区,用于大数据集过滤后,提高小数据集的执行效率,当 spark 程序中,存在过多的小任务的时候,可以通过coalesce 方法,收缩合并分区,减少分区的个数,减小任务调度成本。(该方法不会打乱数据,可能会导致数据倾斜。也可以设置成shuffle,也可以扩大分区,但是需要shuffle,扩大分区时等于repartition)

sortBy 

排序

rdd2.sample(false, 0.4).collect().foreach(println)
println("555555555555555")
rdd2.sortBy(x=>x)
println(rdd2.collect().mkString(","))
println(rdd2.distinct().sortBy(x=>x).collect().mkString(","))
双值类型
val rdd1: RDD[Int] = sparkContext.makeRDD(List(1,2,3,4,9,8,7))
val rdd2: RDD[Int] = sparkContext.makeRDD(List(9,8,7,2,6,5,9))
//交集:intersection,元素类型要相同
println(rdd1.intersection(rdd2).collect().mkString(","))
//并集:union,元素类型要相同
println(rdd1.union(rdd2).collect().mkString(","))
//差集:subtract,区分谁作为主集合,元素类型要相同
println(rdd1.subtract(rdd2).collect().mkString(","))
println(rdd2.subtract(rdd1).collect().mkString(","))
//拉链:zip 将相同位置的数据放在一起,必须是元素数量相同,元素类型相同,分区数相同
println(rdd2.zip(rdd1).collect().mkString(","))
键值类型
partitionBy
/*
*根据指定的规则,对数据进行分区
*分区规则: 默认的为HASH,还有RANGE HashPartitioner
* */
val rdd: RDD[Int] = sparkContext.makeRDD(List(1, 2, 3, 4, 5, 6, 7, 8, 9), 2)
rdd.map((_,1)).partitionBy(new HashPartitioner(2)).collect()
reduceByKey
/*相同的key进行value的聚合
  聚合方式是两两聚合,所以参数有两个,传入的方法是数字相加,字符串拼接等
*其中的key如果只有一个是不会进行运算的 
*/
val rdd: RDD[(String, String)] = sparkContext.makeRDD(List(("chaichai", "hotpot"), ("chaichai", "paopao"), ("yeye", "lorin"), ("yeye", "rainbaby")))
rdd.reduceByKey((x,y)=>x+"&"+y).map(
  data=>data._1+":"+data._2
).collect().foreach(println(_))
groupByKey
/*
* groupByKey将相同的Key放在同一个组中,形成元组
* 元组第一个值为key
* 第二个值为,相同key的value的集合
* */
val rdd: RDD[(String, String)] = sparkContext.makeRDD(List(("chaichai", "hotpot"), ("chaichai", "paopao"), ("yeye", "lorin"), ("yeye", "rainbaby")))
/*
* groupByKey和groupBy的区别
* 1、返回的RDD中groupBy的值原本的是键+值,
*             groupByKey的值为原本的值,因为本身就是根据键分组的
* 2、groupByKey只能根据键分组,而groupBy可以自定义
* */
rdd.groupByKey().collect().foreach(println(_))
rdd.groupBy(_._1).collect().foreach(println(_))
/*
* groupByKey和reducByKey的区别
* 1、reducByKey有一个聚合的概念
* */
包含shuffle操作即打乱数据重新组合的时候,需要落盘(文件交互)
  aggregateByKey &foldByKey
/*
 * aggregateByKey,根据key去聚合,聚合的规则分两种,分区内计算规则和分区间计算规则
 *包含两个参数 aggregateByKey()()
 * 第一个参数是初始比较值,第一个参与凉凉计算的
 * 第二个值是两个函数,第一个 是分区内计算函数,第二个是分区间计算函数
 * */
 val rdd: RDD[(String, Int)] = sparkContext.makeRDD(List(
   ("a", 2), ("a", 4), ("a", 6), ("a", 8)
 ), 2)
rdd.aggregateByKey(5)(
 math.max(_,_),
  _+_
).collect().foreach(println)
 //简化版本foldByKey
 rdd.foldByKey(0)(_+_).collect().foreach(println)
cogroup

groupByKey是对单个 RDD 的数据进行分组

cogroup() 是对多个共享同一个键的 RDD 进行分组 ,相当于先关联,再分组

join

将两个不同的数据源,数据类型为key-value。

将相同的key的value连接在一起形成元组

如果有多个相同的key会形成笛卡尔乘积,造成数据几何增长

leftOuterJoin

类似于sql中的 leftjoin

rightOuterJoin

类似于sql中的 rightjoin

val rdd1: RDD[(Int, String)] = sparkContext.makeRDD(List((4, "d"), (3, "c"), (2, "b"), (1, "a")))
val rdd2: RDD[(Int, String)] = sparkContext.makeRDD(List((4, "D"), (3, "C"), (2, "B"), (1, "A")))
val rdd3: RDD[(Int, String)] = sparkContext.makeRDD(List ((3, "C"), (2, "B"), (1, "A")))
rdd1.join(rdd2).collect().foreach(println(_))
println("########")
rdd1.join(rdd3).collect().foreach(println(_))
println("leftOuterJoin")
rdd1.leftOuterJoin(rdd3).collect().foreach(println)
println("########")
rdd1.leftOuterJoin(rdd3).collect().foreach(println)

RDD行动算子

行动算子:是触发RDD的计算,返回值不是RDD,一般是具体的值

reduce

聚集 RDD 中的所有元素,先聚合分区内数据,再聚合分区间数据

reduce算子是触发计算,返回值不再是RDD

val rdd = sparkContext.makeRDD(List(1, 2, 3, 4, 5, 6, 7, 8, 9))
val result = rdd.reduce(_ + _)
println(s"reduce的结果:${result}")
collect 

在驱动程序中,以数组 Array 的形式返回数据集的所有元素

返回值可以用数组的方法

//collect在驱动程序中,以数组 Array 的形式返回数据集的所有元素
val resultCollect = rdd.collect()
println(s"collect的结果:${resultCollect.mkString}")
println(s"返回数组的最大值:${resultCollect.max}")

count

返回 RDD 中元素的个数

take

返回一个由 RDD 的前 n 个元素组成的数组

val arrayTake = rdd.take(5)
println(s"返回前5个元素为:${arrayTake.mkString(",")}")
takeOrdered

返回该 RDD 排序后的前 n 个元素组成的数组,相当于增加了排序,但是没有新增rdd

val takeOrderedArray = rdd.takeOrdered(3)
println(s"takeOrdered的获取的前三个元素为:${takeOrderedArray.mkString(",")}")
aggregate

分区的数据通过初始值和分区内的数据进行聚合,然后再和初始值进行分区间的数据聚合

val aggregateResult = rdd.aggregate(0)(_ + _, _ + _)
println(s"aggregate的结果:${aggregateResult}")

fold

简化版aggregate,只有一个函数表示的是分区内和分区间一致

countByKey

统计每种 key 的个数

val countByKeyResult = rdd.map(i => (i%2, i )).countByKey()
println(s"countByKey的结果:${countByKeyResult}")
countByKey的结果:Map(0 -> 5, 1 -> 5)

save 相关算子

将数据保存到不同格式的文件中

rdd.saveAsTextFile("output")
1、saveAsTextFile
保存成 Text 文件
def saveAsTextFile(path: String): Unit
rdd.saveAsTextFile("output")
2、saveAsObjectFile
序列化成对象保存到文件
def saveAsObjectFile(path: String): Unit
rdd.saveAsObjectFile("output1")
 3、saveAsSequenceFile
保存成 Sequencefile 文件,要求数据格式必须是K-V类型
def saveAsSequenceFile(
 path: String,
 codec: Option[Class[_ <: CompressionCodec]] = None): Unit
rdd.map((_,1)).saveAsSequenceFile("output2")
foreach

分布式遍历 RDD 中的每一个元素,调用指定函数

行动算子总结

object actionRDD {
  def main(args: Array[String]): Unit = {
    val sparkConf = new SparkConf().setMaster("local[3]").setAppName("mapPartitionsWithIndex")
    val sparkContext = new SparkContext(sparkConf)
    val rdd = sparkContext.makeRDD(List(1, 2, 3, 4, 5, 6, 7, 8, 9,0))
    val result = rdd.reduce(_ + _)
    println(s"reduce的结果:${result}")
    //collect在驱动程序中,以数组 Array 的形式返回数据集的所有元素
    val resultCollect = rdd.collect()
    println(s"collect的结果:${resultCollect.mkString}")
    println(s"返回数组的最大值:${resultCollect.max}")
    //count
    val count = rdd.count()
    println(s"count的结果是:${count}")
    //take
    val arrayTake = rdd.take(5)
    println(s"take返回前5个元素为:${arrayTake.mkString(",")}")
    //takeOrdered
    val takeOrderedArray = rdd.takeOrdered(3)
    println(s"takeOrdered的获取的前三个元素为:${takeOrderedArray.mkString(",")}")
    val aggregateResult = rdd.aggregate(0)(_ + _, _ + _)
    println(s"aggregate的结果:${aggregateResult}")
    val countByKeyResult = rdd.map(i => (i%2, i )).countByKey()
    println(s"countByKey的结果:${countByKeyResult}")
    rdd.saveAsTextFile("output")
    sparkContext.stop()
  }

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值