• spark复习笔记(4):RDD变换


    一、RDD变换

      1.返回执行新的rdd的指针,在rdd之间创建依赖关系。每个rdd都有一个计算函数和指向父rdd的指针

      Spark是惰性的,因此除非调用某个转换或动作,否则不会执行任何操作,否则将触发工作创建和执行。

      2.map()是对每个元素进行变换,应用变换函数,返回的是一个新的分布式数据集,map就是对分区中的每个元素进行一个函数的调用,所以导致出现了那么多;

      map()        //对每个元素进行变换,应用变换函数,(T)=>V,

    package com.jd.test
    
    import org.apache.spark.{SparkConf, SparkContext}
    
    object WordCountDemoScala1 {
      def main(args: Array[String]): Unit = {
         val conf = new SparkConf();
        conf.setAppName("WordCountDemoScala1");
        conf.setMaster("local");
        val sc = new SparkContext(conf);
        val rdd1=sc.textFile("E:/studyFile/data/test.txt");
        val rdd2 = rdd1.flatMap(line=>{ println("flatmap:"+line);line.split(" ")})
        val rdd3 = rdd2.map((_,1));
        val rdd4 = rdd3.reduceByKey(_ + _);
        val r = rdd4.collect();
        r.foreach(println)
      }
    }

      3.mapPartitions()      //对RDD上的每个分区应用一个函数,返回一个新的RDD,输入的是一个迭代器,返回的是一个新的迭代器,可以对每个分区进行函数处理,而不是每个函数。现在是2个线程,四条数据,两条一切割

    
    
    package com.jd.test

    import org.apache.spark.{SparkConf, SparkContext}

    object WordCountDemo3 {
    def main(args: Array[String]): Unit = {
    val conf = new SparkConf();
    conf.setAppName("WordCountDemo3");
    conf.setMaster("local[2]");//local[2]表示开启2个线程来模拟并发程序
    val sc = new SparkContext(conf );
    val rdd1 = sc.textFile("E:/studyFile/data/test.txt",2);//设置最小分区数为2
    val rdd2 = rdd1.flatMap(_.split(" "));
    val rdd3 = rdd2.mapPartitions(it=>{
    import scala.collection.mutable.ArrayBuffer;
    val buf = ArrayBuffer[String]();
    val tname = Thread.currentThread().getName
    println(tname+":"+"mapPartitions start");//将线程加入该分区
    for (e<-it){
    buf.+=("_"+e);
    }
    buf.iterator
    });
    val rdd4 = rdd3.map(word=>{
    val tname=Thread.currentThread().getName
    println(tname+":map"+word);
    (word,1)})
    val rdd5= rdd4.reduceByKey(_ + _);
    rdd5.foreach(println)
    }
    }

      下面演示并发线程数为4,最小分区数为4

    package com.jd.test
    
    import org.apache.spark.{SparkConf, SparkContext}
    
    object WordCountDemo3 {
      def main(args: Array[String]): Unit = {
         val conf = new SparkConf();
        conf.setAppName("WordCountDemo3");
        conf.setMaster("local[4]");//local[4]表示并发线程数为4
        val sc = new SparkContext(conf );
        val rdd1 = sc.textFile("E:/studyFile/data/test.txt",4);//设置最小分区数为4
        val rdd2 = rdd1.flatMap(_.split(" "));
        val rdd3 = rdd2.mapPartitions(it=>{
          import  scala.collection.mutable.ArrayBuffer;
          val buf = ArrayBuffer[String]();
          val tname = Thread.currentThread().getName
          println(tname+":"+"mapPartitions start");//将线程加入该分区
          for (e<-it){
            buf.+=("_"+e);
          }
          buf.iterator
        });
        val rdd4 = rdd3.map(word=>{
          val tname=Thread.currentThread().getName
          println(tname+":map"+word);
          (word,1)})
        val rdd5= rdd4.reduceByKey(_ + _);
        rdd5.foreach(println)
      }
    }

        4.filter()          //过滤器,(T)=>Boolean,返回一个唯一满足滤条件元素的RDD

      5.flatMap()        //压扁,T=>TraversableOnce[U]同上,(Int,Interator)=>Iterator<U>

      6.sample(withReplacement,fraction,seed)    //采样,返回采样的RDD子集。withReplacement元素是否可以多次采样,fraction:期望采样的数量[0,1]

    package com.jd.test
    
    import org.apache.spark.{SparkConf, SparkContext}
    
    object SampleDemo {
      def main(args: Array[String]): Unit = {
         val conf = new SparkConf();
        conf.setAppName("SampleDemo");
        conf.setMaster("local");
        val sc = new SparkContext(conf);
        val rdd1 = sc.textFile("E:/studyFile/data/test.txt");
        val rdd2= rdd1.flatMap(_.split(" "));
    
        val rdd3= rdd2.sample(false,0.5);//可以替换,被抽中的概率是0.5
        rdd3.collect().foreach(println)
      }
    
    }

      7.mapPartitionsWithIndex(func)    //同上(int Iterator<T>)=Iterator<u>。与map函数相类似,但是也提供一个代表分区索引的整数的函数,所以当运行一个T类型的RDD的时候这个函数的类型必须是(Int,Iterator<T>)类型的,

      8.union()            //类似于mysql的union操作,返回一个新的数据集,其中包含元数据集和参数中 数据集的并集。

    package com.jd.test
    
    import org.apache.spark.{SparkConf, SparkContext}
    
    object UnionDemo1 {
      def main(args: Array[String]): Unit = {
         val conf = new SparkConf();
        conf.setMaster("local");
        conf.setAppName("UnionDemo1")
        val sc = new SparkContext(conf);
        val rdd1 = sc.textFile("E:/studyFile/data/test.txt");
        //所有hello行
        val helloRDD=rdd1.filter(_.toLowerCase.contains("hello"));
        //所有world行
        val worldRDD=rdd1.filter(_.toLowerCase.contains("world"));
    
        val allRDD=helloRDD.union(worldRDD);
        allRDD.collect().foreach(println)
    
    
      }
    
    }

                      //select * from persons where id<10  unoin select * from id persons where id>29

      9.intersection          //取出交集,提取两个rdd都含有的元素

    package com.jd.test
    
    import org.apache.spark.{SparkConf, SparkContext}
    
    object IntersectionDemo1 {
      def main(args: Array[String]): Unit = {
        val conf = new SparkConf();
        conf.setAppName("IntersectionDemo1");
        conf.setMaster("local");
        val sc = new SparkContext(conf);
        val rdd1 = sc.textFile("E:/studyFile/data/test.txt");
        val rdd2 = rdd1.flatMap(_.split(" "));
        val helloRDD = rdd2.filter(_.toLowerCase.contains("llo"));
        val worldRDD=rdd2.filter(_.toLowerCase.contains("wor"));
        val intersectRDD= helloRDD.intersection(worldRDD);
        intersectRDD.collect().foreach(println)
      }
    }

      10.distinct([numTasks])      //去重操作 

    package com.jd.test
    
    import org.apache.spark.{SparkConf, SparkContext}
    
    object DistinctDemo{
      def main(args: Array[String]): Unit = {
        val conf = new SparkConf();
        conf.setMaster("local")
        conf.setAppName("DistinctDemo");
        val sc = new SparkContext(conf);
        val rdd1 =sc.textFile("E:/studyFile/data/test.txt");
        val rdd2 = rdd1.flatMap(_.split(" "));
        val rdd3= rdd2.distinct()
        rdd3.collect().foreach(println)
      }
    }

      11.reduceByKey(*)        //按照key进行聚合

      12.groupByKey()          //按照key进行分组(K,V)=>(k,Iterable<V>),当你在(K,V)对上调用这个函数的时候,结果会返回一个可以迭代的量(K,Iterable<V>),相同key值的数据别合在一起了。 

    package com.jd.test
    
    import org.apache.spark.{SparkConf, SparkContext}
    
    object GroupByKeyDemo {
      def main(args: Array[String]): Unit = {
         val conf = new SparkConf();
        conf.setAppName("GroupByKeyDemo")
        conf.setMaster("local");
        val sc = new SparkContext(conf);
        val rdd1 = sc.textFile("E:/codes/stus.txt");
        val rdd2 = rdd1.map(line=>{
          val key = line.split(" ")(3)
          (key,line);
    
        });
        //通过key来进行分组
        val rdd3 = rdd2.groupByKey();
        rdd3.collect().foreach(t=>{
          val key = t._1;
          println(key+":=================================================================>")
          for(e <- t._2){
            println(e)
          }
    
        })
    
      }
    
    }

      13.reduceByKey(func,[numTasks])

      当在(k,v)键值对上调用一个数据结集的时候,结果返回一个键值对,其中每个键对应的值都给定一个聚合函数func进行聚合,其类型必须是(V,V)=>V。同groupByKey一样,reduce的任务数通过第二个可选的参数进行指定

      14.sortByKey([ascending],[numTasks])    //按key进行排序

      15.join(otherDataset,[numTasks])      //横向连接,按key来进行联合,当你调用数据集(K,V)和(K,W)的时候,会返回一个新的数据集(K,(V,W))

      16.cogroup协分组      //(K,V).cogroup(K,W)=>(K,(Iterable<V>,Iterator<W>))

    package com.jd.test
    
    import org.apache.spark.{SparkConf, SparkContext}
    
    object CogroupDemp {
      def main(args: Array[String]): Unit = {
        val conf = new SparkConf();
        conf.setAppName("CogroupDemp");
        conf.setMaster("local[4]");
        val sc = new SparkContext(conf);
        val rdd1 =sc.textFile("E:/codes/cogroup-1.txt")
        val rdd2 =rdd1.map(line=>{
          val arr = line.split(" ");
          (arr(0),arr(1));
        });
    
        val rdd3 = sc.textFile("E:/codes/cogroup-2.txt");
        val rdd4 = rdd3.map(line=>{
          val arr = line.split(" ");
          (arr(0),arr(1))
        });
        val rdd = rdd2.cogroup(rdd4);
        rdd.collect().foreach(t=>{
          println(t._1+":============================================>")
          for(e<-t._2._1){
            println(e)
          }
          for (e<-t._2._2){
            println(e)
          }
        })
      }
    }

      17.cartesian(otherDataset)  //笛卡尔积,RR[T]=>RDD[(T,U)]。调用类型T和类型U的数据集,返回(T,U)所对的数据集

    package com.jd.test
    
    import org.apache.spark.{SparkConf, SparkContext}
    
    //计算笛卡尔积
    object cartesianDemo {
      def main(args: Array[String]): Unit = {
        val conf = new SparkConf();
        conf.setMaster("local[4]");
        conf.setAppName("cartesianDemo");
        val sc = new SparkContext(conf);
        val rdd1 = sc.parallelize(Array("tom","jack","peter","stone","mike"));
        val rdd2 = sc.parallelize(Array("1234","2345","3456","5678"));
        val rdd3 = rdd1.cartesian(rdd2);
         rdd3.collect().foreach(t=>println(t))
      }
    
    }

      18.pipe          //将rdd的元素传递给脚本或者命令

      19.coalesce(numPartitions)  //降低RDD中的分区数到指定的分区数

      20.repartition        //重新分区,分区数可增可减

    package com.jd.test
    
    import org.apache.spark.{SparkConf, SparkContext}
    
    object SaveAsTextDemo {
      def main(args: Array[String]): Unit = {
         val conf = new SparkConf();
        conf.setMaster("local");
        conf.setAppName("SaveAsTextDemo");
        val sc = new SparkContext(conf);
        val rdd1 = sc.textFile("E:/codes/test.txt");
        val rdd2 = rdd1.flatMap(_.split(" "));
        val rdd3 = rdd2.map((_,1));
        //Merge the values for each key using an associative and commutative reduce function. This will
        //   * also perform the merging locally on each mapper before sending results to a reducer, similarly
        //   * to a "combiner" in MapReduce.
        val rdd4 = rdd3.reduceByKey(_ + _,3);//指定分区数为3,按key聚合,同时还指定分区数
        rdd4.saveAsTextFile("E:/codes/out")
    
      }
    }

      21.repartiotion        //在RDD中重新进行shuffle操作,来随机的创建更多或者更少的分区,以及通过他们来进行分区的平衡,这经常用在网络间数据的shuffle

      22.repartitionAndSortWithinPartitions(partitioner)    //再分区并且排序

    二、RDD Action

    ------------------------------------------------------------------

      1.collect()      //在客户端返回数据集的所有元素来作为数组,这在筛选器或其他操作返回足够小的数据子集之后非常有用。

      2.reduce()      //使用函数func(携带两个参数并返回一个参数)聚合数据集的元素,函数应该可以通信以及关联

      3.count        //返回数据集中RDD元素的个数,形成数组,手机RDD元素形成数组

      4.first          //只取第一个元素

      5.take(n)        //去除前n个元素

      6.takeOrdered(n,[ordering])  //返回RDD的前n个元素,使用自然顺序或者用户比较器

      7.saveAsTextFile(path)    //保存到文件中去

      8.saveAsSequenceFile(path)  //保存成序列文件

      9.countByKey()        //按照key进行统计

    三、Spark数据倾斜

        数据倾斜问题,map阶段对key进行重新划分

  • 相关阅读:
    枚举
    交房租
    Schtasks 命令详解
    记录自己在 cmd 中执行 jar 文件遇到的一些错误
    Java 8 日期时间 API
    Java 8 Optional 类
    Java 8 Stream
    Java 8 默认方法
    Java 8 函数式接口
    Java 8 方法引用
  • 原文地址:https://www.cnblogs.com/bigdata-stone/p/9893140.html
Copyright © 2020-2023  润新知