有了上面三篇的函数,平时开发应该问题不大了。
这篇的主要目的是把所有的函数都过一遍,深入RDD的函数

RDD函数大全

数据准备
val sparkconf = new SparkConf().setAppName("test_Spark_sql").setMaster("local[2]")
        val spark = SparkSession.builder().config(sparkconf).config("spark.driver.host", "localhost").getOrCreate().sparkContext
        spark.setCheckpointDir("/data/checkpoint/")
        val data = spark.makeRDD(Array(("C",3),("D",4),("A",11), ("B",2), ("B",1))).persist()
了解函数
println(data.id)//为RDD起一个ID  默认是1开始+
        data.setName("rdd")//为RDD设置name
        println(data.name)//为RDD起一个name 可以设置名称 未设置打印null
        println(data.+("|"))//显示当前类的部分信息  例如:ParallelCollectionRDD[0] at makeRDD at Test_SensorsData.scala:35
        data.barrier()  //将当前阶段标记为障碍阶段  实验性的功能  可以不用关注
        println(data.toDebugString) //调试信息   (2) ParallelCollectionRDD[0] at makeRDD at Test_SensorsData.scala:35 [Memory Deserialized 1x Replicated]
        println(data.isInstanceOf[java.math.BigDecimal]) //判断是否是这个类型的类
        data.context //返回SparkContext
缓存,chechpoint 分区相关方法
data.cache()//缓存数据  默认是内存缓存
        data.persist()//缓存数据  默认是内存缓存
        data.persist(org.apache.spark.storage.StorageLevel.MEMORY_ONLY)
        data.unpersist()   //去掉缓存
        data.checkpoint()  //进行数据checkpint
        println(data.isCheckpointed)//当前RDD是否有Checkpoint
        println(data.getStorageLevel)//当前存储等级
        println(data.getCheckpointFile.mkString("|")) //打印Checkpoint文件名称
        data.localCheckpoint()//在本地文件进行 Checkpoint
        data.coalesce(1) //RDD重分区   直接合并文件
        data.repartition(1)//RDD重分区   有shuffle操作

        data.partitionBy(new org.apache.spark.HashPartitioner(4)).collect().foreach(print)
        data.partitioner.map(print)//是按照什么方式分区的
        print(data.partitions(0))//获取该RDD的第一个分区
        data.preferredLocations(data.partitions(0))//拿到这个RDD分区的最佳物理位置
        data.dependencies.foreach(println)//依赖关系 org.apache.spark.OneToOneDependency@6e1b9411
统计 取样 判断
println(data.first())//第一个元素
        data.top(3).foreach(println)

        data.lookup("B").foreach(print)//根据Key查找
        print(data.map(_._2).reduce((x,y)=>(x+y)))//sum函数一样的
        println(data.max())//最大值
        println(data.min())//最小值
        println(data.count())//RDD长度    返回Long类型
        println(data.countByKey())//统计key出现的次数    返回Map类型
        println(data.countByValue())//统计key+value出现的次数    返回Map类型
        data.keys.collect().foreach(print)//拿到所有的key  不去重
        data.values.collect().foreach(print)//输出所有的value值

        data.randomSplit(Array(0.2,0.8)).apply(0).collect().map(println)//随即切分RDD  这个感觉没有啥实际意义

        data.collect().map(println) //将RDD的数据收集到Driver端
        val f : PartialFunction[Int,Boolean] = {case 1 => true case 2 => true case _ => false}
        data.map(x=>x._2).collect(f).foreach(x=>print(x+"|"))   //参数变化
        data.collectAsMap().foreach(print)//将数据集收成Map
        data.collectAsync().get().foreach(print)//将数据集收成FutureAction

        data.take(3).foreach(println) //返回多少数据
        data.takeOrdered(3).foreach(println) //先排序  在返回数据
        data.takeSample(true,5).foreach(println)//随机取样
        println(data.sample(true,0.5).collect().length)//是否允许多次采样|采样比例  随机采样函数
        println(data.sampleByKey(false,Map("A"->0.2,"B"->0.4,"C"->0.2,"D"->0.2)).collect().length)//是否允许多次采样|后面的KEY必须枚举  我要知道key枚举,还算个毛
        println(data.sampleByKeyExact(false,Map("A"->0.2,"B"->0.4,"C"->0.2,"D"->0.2)).collect().length)//是否允许多次采样|后面的KEY必须枚举  我要知道key枚举,还算个毛

        println(data.countApprox(1000,0.1d))//近似统计功能 第一个数字是任务统计时长 第二个数字是精度越小精度越高(0-1)之间
        println(data.countByKeyApprox(1000,0.1d))//统计key出现的次数    第一个数字是任务统计时长 第二个数字是精度越小精度越高(0-1)之间
        println(data.countByValueApprox(1000,0.35))//value近似统计功能 第一个数字是任务统计时长 第二个数字是精度越小精度越高(0-1)之间
        println(data.countApproxDistinct(0.2))//近似统计功能  默认精度0.5
        println(data.countApproxDistinct(31,54))//近似统计功能  第一个参数:4<=第二个参数<=32之间    第二个参数:0<=第二个参数<=32之间
        println(data.countApproxDistinctByKey(0.3))//近似统计功能  默认精度0.5  必须大于0.000017
        println(data.countApproxDistinctByKey(0.3,null))//近似统计功能  默认精度0.5  必须大于0.000017  第二个参数partitioner
        println(data.countApproxDistinctByKey(4,7,null))//近似统计功能  第一个参数:4<=第二个参数<=32之间    第二个参数:0<=第二个参数<=32之间  第三个参数partitioner
        println(data.countApproxDistinctByKey(4,7))//近似统计功能  第一个参数:精度    第二个参数:返回RDD的分区数

        println(data.isEmpty())     //当前RDD是否为空
        print(data.toJavaRDD().collect().toString)//转换成javaRDD
        println(data.toLocalIterator.take(1))//转换成迭代器
排序
data.sortBy(x=>x._1).collect().foreach(println)//按照给定的字段排序
        data.sortByKey().collect().foreach(println)//按照key排序  数据必须是key value格式的数据 不然会报错
转换操作
data.glom().take(1).map(_.map(print))//把一个分区的所有的元素放到一个RDD[Array]
        data.map(x=>x).collect().foreach(println)  //map循环
        def mapValue (y:Int) = {y+1}
        data.mapValues(mapValue).collect().foreach(print)// value 转换函数
        data.mapPartitions(x=>x.map(x=>(x._1,x._2+1))).collect().foreach(println)  //每一次循环处理一个Partition
        data.mapPartitionsWithIndex((index, data)=>data.map(x=>(index,x._1,x._2+1)).toIterator).collect().foreach(println)//每一次循环处理一个Partition带下标
        data.pipe("cat").collect().foreach(println)  //可以执行外部命令的  暂时没有看懂  方法先记下
        data.filter(_._2>5).collect().map(println)//条件过滤

        data.flatMap(x=>Array(x._1,x._2)).collect().map(println)//一行变多行
        data.flatMapValues(x=>Array(x,x,x)).collect().foreach(print)//把value 展开
        println(data.map(x=>x._2).fold(0)((c1, c2) => {c1 + c2}))//聚合运算
        data.foreachPartition(x=>x.take(100).foreach(print))//对每个分区都进行这个操作  可以写数据库
join
println(data.++(data))//sql中的unionAll操作   不去重
        data.union(data).collect().map(println)//union all
        println(data.cartesian(data))//两个RDD的笛卡尔积
        data.intersection(data.filter(_._2==2)).collect().map(print)//两个RDD交集
        data.intersection(data.filter(_._2==2),2).collect().map(print)//两个RDD交集
        data.subtract(data.filter(_._2.equals(1))).collect().map(println) //left anti
        data.subtract(data.filter(_._2.equals(1)),4).collect().map(println) //left anti  第二个参数分区数
        import org.apache.spark.HashPartitioner
        data.fullOuterJoin(data.filter(_._2 ==1)).collect().foreach(print)// sqlboy 应该能理解 full join
        data.fullOuterJoin(data.filter(_._2 ==1),4).collect().foreach(print)// 上同 分区
        data.fullOuterJoin(data.filter(_._2 ==1),new HashPartitioner(4)).collect().foreach(print)// 上同 分区
        data.leftOuterJoin(data).collect().foreach(print)// left join  第二个RDD的解过用Some包含起来 (B,(2,Some(2)))
        data.leftOuterJoin(data,4).collect().foreach(print)// 上同 分区
        data.leftOuterJoin(data,new HashPartitioner(4)).collect().foreach(print)// 上同 分区
        data.join(data).collect().foreach(print)//join
        data.join(data,4).collect().foreach(print)//上同 分区
        data.join(data,new HashPartitioner(4)).collect().foreach(print)//上同 分区
        data.rightOuterJoin(data).collect().foreach(print) // right join  第一个RDD的解过用Some包含起来 (B,(2,Some(2)))
        data.rightOuterJoin(data,4).collect().foreach(print) // 上同 分区
        data.rightOuterJoin(data,new HashPartitioner(4)).collect().foreach(print) // 上同 分区
        data.subtractByKey(data.filter(_._2==1)).collect().foreach(print)//left anti
        data.subtractByKey(data.filter(_._2==1),4).collect().foreach(print)//上同 分区
        data.subtractByKey(data.filter(_._2==1),new HashPartitioner(4)).collect().foreach(print)//上同 分区
        //------------------非正常join----------
        data.zip(data).collect().map(println)//两个RDD进行压缩  第一个和第一个合并
        data.zipWithIndex().collect().map(print)//带下标的压缩
        data.zipWithUniqueId().collect().map(print)//带下标的压缩
        data.cogroup(data).collect().map(print)//根据key 同一个rdd放到一个CompactBuffer  不同rdd元组
        data.cogroup(data,2).collect().map(print)//上同  分区个数
        data.cogroup(data,new HashPartitioner(2)).collect().map(print)//上同  分区个数
        data.cogroup(data.filter(x=>(x._2==1 || x._2==2)),data.filter(x=>(x._2==1 ))).collect().map(print)//三个RDD
        data.cogroup(data.filter(x=>(x._2==1 || x._2==2)),data.filter(x=>(x._2==1 )),4).collect().map(print)//上同  分区个数
        data.cogroup(data.filter(x=>(x._2==1 || x._2==2)),data.filter(x=>(x._2==1 )),new HashPartitioner(4)).collect().map(print)//上同  分区个数
        data.cogroup(data,data,data).collect().map(print)//四个RDD
        data.cogroup(data,data,data,4).collect().map(print)//上同  分区个数
        data.cogroup(data,data,data,new HashPartitioner(4)).collect().map(print)//上同  分区个数
文件操作
data.saveAsTextFile("/data/dd")//保存文件 文本格式 在里面还是(A,11)
        data.saveAsTextFile("/data", classOf[org.apache.hadoop.io.compress.CompressionCodec])//保存文件  压缩
        data.saveAsObjectFile("")//保存文件格式  SequenceFile格式
        //--------NewAPI------
        import org.apache.hadoop.mapred.JobConf
        val jobConf = new JobConf()
        jobConf.setOutputKeyClass(classOf[java.lang.String])
        jobConf.setOutputValueClass(classOf[java.lang.Integer])
        jobConf.set("mapred.output.dir", "/data/dd/")
        data.saveAsNewAPIHadoopDataset(jobConf)
        //必须这个类下面的包才行  org.apache.hadoop.mapred.TextOutputFormat 这个不行
        data.map(x=>(java.lang.String.valueOf(x._1),java.lang.Integer.valueOf(x._2))).saveAsNewAPIHadoopFile[org.apache.hadoop.mapreduce.lib.output.TextOutputFormat[String,Integer]]("/data/dd/")
        data.saveAsNewAPIHadoopFile("/data/dd/",classOf[java.lang.String],classOf[java.lang.Integer],classOf[org.apache.hadoop.mapreduce.lib.output.TextOutputFormat[java.lang.String,java.lang.Integer]])
        //--------OldAPI------
        val conf = new JobConf()
        conf.set("mapreduce.output.fileoutputformat.outputdir","/data/dd/")
        conf.setOutputKeyClass(classOf[java.lang.String])
        conf.setOutputValueClass(classOf[java.lang.Integer])
        conf.setOutputFormat(classOf[org.apache.hadoop.mapred.TextOutputFormat[java.lang.String,java.lang.Integer]])
        conf.setOutputCommitter(classOf[org.apache.hadoop.mapred.FileOutputCommitter])
        data.saveAsHadoopDataset(conf)
        data.saveAsHadoopFile("/data/dd/",classOf[java.lang.String],classOf[java.lang.Integer],classOf[org.apache.hadoop.mapred.TextOutputFormat[java.lang.String,java.lang.Integer]])
        data.map(x=>(java.lang.String.valueOf(x._1),java.lang.Integer.valueOf(x._2))).saveAsHadoopFile[org.apache.hadoop.mapred.TextOutputFormat[java.lang.String,java.lang.Integer]]("/data/dd/")
RDD 聚合函数
//--------聚合后还是RDD------
        data.distinct()//所有字段去重 方法  背后是reduceBykey
        data.distinct(4)//reduceBykey的时候 使用第二个参数
        data.groupBy(_._1).collect().map(print)//把这一列作为新的列,然后groupby (D,CompactBuffer((D,4))) (A,CompactBuffer((A,11)))
        def get2(tuple2:Tuple2[String,Int]): String = tuple2._1
        data.groupBy(get2 _,4).collect().map(print)//把这一列作为新的列,然后groupby 按照四个分区
        data.keyBy(get2).collect().map(print)//新建一列key
        data.aggregateByKey(0)(_+_,_+_).collect().map(print)//根据key聚合 第一个函数partition内聚合  第二个函数partition之间聚合
        data.aggregateByKey(0,4)(_+_,_+_).collect().map(print)//上同  分区个数
        data.combineByKey(x=>List[Int](x),(x:List[Int],y:Int)=>x.::(y),(x:List[Int],y:List[Int])=>x.:::(y)).collect().foreach(println)//聚合函数 分区形式的总是报错
        data.combineByKey(x=>x,(x:Int,y:Int)=>x+y,(x:Int,y:Int)=>x+y).collect().foreach(println)
        data.combineByKeyWithClassTag(x=>List[Int](x),(x:List[Int],y:Int)=>x.::(y),(x:List[Int],y:List[Int])=>x.:::(y)).collect().foreach(println)//聚合函数 分区形式的总是报错
        data.combineByKeyWithClassTag(x=>x,(x:Int,y:Int)=>x+y,(x:Int,y:Int)=>x+y).collect().foreach(println)
        data.foldByKey(0)(_+_).collect().foreach(print)//分区内和分区间的都是用这个聚合方式
        data.foldByKey(0,new HashPartitioner(4))(_+_).collect().foreach(print)//上同  分区个数
        data.foldByKey(0,4)(_+_).collect().foreach(print)//上同  分区个数
        data.groupByKey.collect().foreach(print) //group by key  value放到一个CompactBuffer里面
        data.groupByKey(4).collect().foreach(print) //上同 分区
        data.groupByKey(new HashPartitioner(4)).collect().foreach(print) //上同 分区
        data.groupWith(data).collect().foreach(print)//groupByKey + join (B,(CompactBuffer(2, 1),CompactBuffer(2, 1)))
        data.groupWith(data,data).collect().foreach(print)//上同 三个RDD
        data.groupWith(data,data,data).collect().foreach(print)//上同 四个RDD
        data.reduceByKey(_+_).collect().foreach(print)//把value聚合
        data.reduceByKey(_+_,4).collect().foreach(print)//上同 分区
        data.reduceByKey(new HashPartitioner(4),_+_).collect().foreach(print)//上同 分区
        //--------聚合后是非RDD------
        def combOp(c1: Int, c2: Int): Int = {c1 + c2}
        println(data.map(x=>x._2).treeAggregate(0)(combOp,combOp))  //以树的方式合并这个RDD   先根据树的深度预聚合,后面在聚合 第一个参数初始化数字
        println(data.map(x=>x._2).treeReduce(combOp,2))//以树的方式合并这个RDD   先根据树的深度预聚合,后面在聚合
        println(data.map(_._2).aggregate(0)((x,init)=>(x+init),(par1,par2)=>(par1+par2)))
        data.reduceByKeyLocally(_+_).foreach(print)//客户端聚合后   直接把map结果发送给master  这个一般还是不用的好