Spark基础02 RDD算子01 转换算子 行动算子 分区数 三种RDD创建方式 控制台打印日志 map filter reduceByKey collect take

RDD
触发Action就会生成spark job
RDD的全称为Resilient Distributed Dataset,是一个弹性、可复原的分布式数据集是Spark中最基本的抽象,是一个不可变的、有多个分区的、可以并行计算的集合。
RDD中并不装真正要计算的数据,而装的是描述信息,描述以后从哪里读取数据,调用了用什么方法,传入了什么函数,以及依赖关系等。

RDD特点
有一些列连续的分区:分区编号从0开始,分区的数量决定了对应阶段Task的并行度
 有一个函数作用在每个输入切片上: 每一个分区都会生成一个Task,对该分区的数据进行计算,整函数就是具体的计算逻辑
 RDD和RDD之间存在一些列依赖关系:RDD调用Transformation后会生成一个新的RDD,子RDD会记录父RDD的依赖关系,包括宽依赖(有shuffle)和窄依赖(没有shuffle)
 (可选的)K-V的RDD在Shuffle会有分区器,默认使用HashPartitioner
 (可选的)如果从HDFS中读取数据,会有一个最优位置:spark在调度任务之前会读取NameNode的元数据信息,获取数据的位置,移动计算而不是移动数据,这样可以提高计算效率。

RDD算子的分类
 Transformation:即转换算子,调用转换算子会生成一个新的RDD,Transformation是Lazy的,不会触发job执行。
 Action:行动算子,调用行动算子会触发job执行,本质上是调用了sc.runJob方法,该方法从最后一个RDD,根据其依赖关系,从后往前,划分Stage,生成TaskSet。

RDD的分区

lines.partitions.length 分区个数,查看RDD分区数量

sc.textFile(“hdfs://linux201:9000/data”, 6 ) 可以指定分区数6

val arr = Array(1, 2, 3, 4, 5, 6, 7, 8, 9)
val rdd = sc.parallelize(arr)
把普通的 scala集合 转成 分布式的集合,在集群运行
分区数为设置的默认的分区数
rdd.sum
val rdd = sc.parallelize(arr, 2) 可设置分区数2

通过并行化方式,将Driver端的集合转成RDD
val rdd1: RDD[Int] = sc.parallelize(Array(1,2,3,4,5,6,7,8))
从HDFS指定的目录据创建RDD
val lines: RDD[String] = sc.textFile(“hdfs://node-1.51doit.cn:9000/log”)
使用上面两种方式创建RDD都可以指定分区的数量

Transformation算子map
map算子,功能所做映射
val rdd1: RDD[Int] = sc.parallelize(List(5,6,4,7,3,8,2,9,1,10)).map(_*2)

flatMap算子,先map在压平,spark中没有flatten方法
val rdd2 = sc.parallelize(Array(“a b c”, “d e f”, “h i j”))
rdd2.flatMap(.split(’ ')).collect
val rdd3 = sc.parallelize(List(List(“a b c”, “a b b”),List(“e f g”, “a f g”)))
rdd3.flatMap(
.flatMap(_.split(" "))).collect

mapPartitions,将数据以分区为的形式返回进行map操作,一个分区对应一个迭代器,该方法和map方法类似,只不过该方法的参数由RDD中的每一个元素变成了RDD中每一个分区的迭代器,如果在映射的过程中需要频繁创建额外的对象,使用mapPartitions要比map高效的过。
val rdd1 = sc.parallelize(List(1, 2, 3, 4, 5), 2)
var r1: RDD[Int] = rdd1.mapPartitions(it => it.map(x => x * 10))

mapPartitionsWithIndex,类似于mapPartitions, 不过函数要输入两个参数,第一个参数为分区的索引,第二个是对应分区的迭代器。函数的返回的是一个经过该函数转换的迭代器。
val rdd1 = sc.parallelize(List(1,2,3,4,5,6,7,8,9), 2)
rdd1.mapPartitionsWithIndex(func).collect
index分区号,it方法
numbers.mapPartitionsWithIndex((index, it)) => {
it.map(e => s"partition: $index, val: $e")
}

sortByKey
groupByKey

sortBy算子,排序 是transformation但是会触发action(触发目的:进行采样操作方便排序)
sc.parallelize(List(5,11,22,13,2,1,10)).sortBy(x=>x,true)
sc.parallelize(List(5,11,22,13,2,1,10)).sortBy(x=>x+"",true)
sc.parallelize(List(5,11,22,13,2,1,10)).sortBy(x=>x.toString,true)

sortByKey算子,排序
val rdd1 = sc.parallelize(List((“hello”, 9), (“tom”, 8), (“kitty”, 7), (“tom”, 2)))
val rdd2 = rdd1.sortByKey()

groupBy算子,安装key分组
val rdd1 = sc.parallelize(List((“hello”, 9), (“tom”, 8), (“kitty”, 7), (“tom”, 2)))
val rdd2 = rdd1.groupBy(_._1)

groupByKey 按照key进行分组
val rdd2 = sc.parallelize(List((“jerry”, 9), (“tom”, 8), (“shuke”, 7), (“tom”, 2)))
val rdd2: RDD[(String, Iterable[Int])] = rdd1.groupByKey()

reduceByKey
val rdd2 = sc.parallelize(List((“jerry”, 9), (“tom”, 8), (“shuke”, 7), (“tom”, 2)))
val rdd3 = rdd1.reduceByKey(+)

distinct算子,去重
sc.parallelize(List(5,5,6,6,7,8,8,8)).distinct.collect

val rdd6 = sc.parallelize(List(5,6,4,7))
val rdd7 = sc.parallelize(List(1,2,3,4))
val rdd8 = rdd6.union(rdd7)

 intersection算子,交集
val rdd6 = sc.parallelize(List(5,6,4,7))
val rdd7 = sc.parallelize(List(1,2,3,4))
val rdd9 = rdd6.intersection(rdd7)

 subtract算子,差集
val rdd6 = sc.parallelize(List(5,6,4,7))
val rdd7 = sc.parallelize(List(1,2,3,4))
val rdd9 = rdd6.subtract(rdd7)

RDD简介
读取HDFS数据
读取本地数据
本地结合的转换
RDD调用转换算子获取RDD
RDD中分区和任务的划分
算子 转换算子RDD -RDD
map
filter
flatMap
mapPartitions
mapPartitionWithIndex

行动算子
foreach
collect()
take()
takeSample
takeOrdered

object CreateRDDFromDisk {
  def main(args: Array[String]): Unit = {
    val sc: SparkContext = SparkUtils.getSparkContext
    //本地的list集合
    val ls = List("a", "b", "c", "d", "e", "f")
    val ls2: List[(String, Int)] = ls.map((_, 1))
    //将存储对偶元组的list转换成Map集合
    val mp: Map[String, Int] = ls2.toMap
    mp.toArray
    mp.toList
    mp.toSet
    mp.toSeq
    val rdd1: RDD[(String, Int)] = sc.parallelize(mp.toList)

    sc.stop()

  }

  private def lsToRDD(sc: SparkContext) = {
    val bs: BufferedSource = Source.fromFile("d://word.txt")
    val ls2 = bs.getLines().toList
    sc.parallelize(ls2)


    val ls = List("a", "b", "c", "d", "e", "f")
    val rdd1: RDD[String] = sc.parallelize(ls)
    val rdd2: RDD[String] = sc.parallelize(ls, 3)

    println(rdd1.partitions.size)
    println(rdd2.partitions.size)
  }

  /**
   * 数组转成RDD
   *
   * @param sc
   */
  private def arrToRDD(sc: SparkContext) = {
    //创建一个本地数组
    val arr = Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)
    //将本地结合转成RDD
    val rdd1 = sc.makeRDD(arr)
    //参数1 本地集合  参数2 指定分区个数
    //val rdd2 = sc.makeRDD(arr, 3)

    //参数1 集合 参数2 分区数据
    sc.parallelize(arr, 4)

    /**
     * 在本地运行模式中sc对象默认使用的是local[*]所有的核数据
     * 机器8核 同时能8线程 最大限度的并行运行 8个任务 8个分区
     */

    println(rdd1.partitions.size)
  }
}
object CreateRDDFromHdfsFile {
  def main(args: Array[String]): Unit = {
    //设置控制台打印日志的级别
    Logger.getLogger("org").setLevel(Level.ERROR)
    //hdfs的本地用户名
    System.setProperty("HADOOP_USER_NAME", "root")
    //获取spark对象
    val conf: SparkConf = new SparkConf()
    //设置本地测试运行模式 设置app名称
    conf.setMaster("local[*]").setAppName(this.getClass.getSimpleName)
    val sc = new SparkContext(conf)
    //读取HDFS数据
    val rdd1: RDD[String] = sc.textFile("hdfs://linux201:9000/word.txt")
    //获取当前RDD的分区数
    val psize: Int = rdd1.partitions.size
    //打印
    println(psize)

    sc.stop()


  }

}

object FilterFunction {
  def main(args: Array[String]): Unit = {

    val sc: SparkContext = SparkUtils.getSparkContext
    val arr: Array[Int] = Array(1, 3, 45, 6, 7, 7, 8, 9)

    val rdd: RDD[Int] = sc.parallelize(arr, 3)
    val rdd1: RDD[Int] = rdd.map(_ * 10)
    //val rdd2: RDD[Int] = rdd1.filter(_ > 30)
    //val rdd2: RDD[Int] = rdd1.filter(_ > 2).filter(_ % 2 == 0)
    val rdd2 = rdd1.filter(e => e > 2 && e % 3 == 0)

    rdd2.foreach(println)

  }

}
object FlatMapFunction {
  def main(args: Array[String]): Unit = {
    val sc = SparkUtils.getSparkContext
    val rdd: RDD[String] = sc.textFile("d://word.txt")
    //对每行数据进行切割压平
    val rdd2: RDD[String] = rdd.flatMap(_.split(" "))
    //(单词, 1) (单词, 1)
    val rdd3: RDD[(String, Int)] = rdd2.map((_, 1))
    //将相同的单词聚合
    val rdd4: RDD[(String, Int)] = rdd3.reduceByKey(_ + _)

    //行动算子
    rdd4.foreach(println)
  }

}
object MapFunctionDemo {
  def main(args: Array[String]): Unit = {

    val arr = Array(1, 2, 4, 5, 6, 7)

    val sc: SparkContext = SparkUtils.getSparkContext

    val rdd1: RDD[Int] = sc.parallelize(arr, 3)
    //rdd1调用map方法.方法中的函数作用在每一个元素上执行 arr.size
    //由 rdd1调用map算子返回一个处理之后的新rdd2,map是一个转换算子

    val rdd2 = rdd1.map(e => e * 10)
    //rdd2 调用filter函数 ,返回一个处理后的新rdd filter转换算子
    val rdd3: RDD[Int] = rdd2.filter(_ > 20)



  }

}
object MapPartitionsDemo {
  def main(args: Array[String]): Unit = {

    val sc: SparkContext = SparkUtils.getSparkContext

    val ls: List[String] = List("tom", "hello", "cat", "jack", "jerry")
    val rdd1= sc.parallelize(ls, 3)
    //val rdd2 = rdd1.map(_.toUpperCase)
    val rdd2: RDD[String] = rdd1.mapPartitions(iters => {
      println(Thread.currentThread() + "**")
      for (elem <- iters) yield elem.toUpperCase + "aaa"
    })

    rdd2.foreach(println)

  }

}

object MapPartitionWithIndexFunctionDemo {
  def main(args: Array[String]): Unit = {

    val sc: SparkContext = SparkUtils.getSparkContext
    val arr: Array[String] = Array("a", "o", "b", "c", "u")

    val rdd1: RDD[String] = sc.parallelize(arr, 3)
    val rdd2 = rdd1.mapPartitionsWithIndex((index, iters) => {
      for (elem <- iters) yield index + "---" + elem
    })
    //执行行动算子,将RDD的结果收集到本地 行动算子
    /**
     * collect行动算子 调用行动算子 触发job 开始处理运算数据
     */
    val res: Array[String] = rdd2.collect() //收集成本地集合
    res.foreach(println)

  }

}
object TakeFunction {
  def main(args: Array[String]): Unit = {

    val sc: SparkContext = SparkUtils.getSparkContext
    val arr = Array(7, 6, 2, 5, 11, 14, 8, 19)
    val rdd: RDD[Int] = sc.parallelize(arr, 3)

    //take行动算子 从0号区开始取值,顺序取
    val res: Array[Int] = rdd.take(3)

    for (elem <- res) {
      println(elem)
    }

    sc.stop()
  }

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值