大数据Spark02算子

来源:互联网 发布:淘宝网页显示不正常 编辑:程序博客网 时间:2024/06/06 17:38

 Spark代码流程

1. 创建SparkConf对象。

-- 可以设置Application name。

--可以设置运行模式及资源需求。

2. 创建SparkContext对象。

3. 基于Spark的上下文创建一个RDD,对RDD进行处理。

4. 应用程序中要有Action类算子来触发Transformation类算子执行。

5.关闭Spark上下文对象SparkContext。

SparkRdd的创建方式

基于sparkContext对象创建
1)从Hadoop文件系统(如HDFS、Hive、HBase)输入创建。
2)从父RDD转换得到新RDD。
3)通过parallelize或makeRDD将单机数据创建为分布式RDD。
4)基于DB(Mysql)、NoSQL(HBase)、S3(SC3)、数据流创建。

从集合创建RDD

  • parallelize

def parallelize[T](seq: Seq[T], numSlices: Int = defaultParallelism)(implicit arg0: ClassTag[T]): RDD[T]

从一个Seq集合创建RDD。

参数1:Seq集合,必须。

参数2:分区数,默认为该Application分配到的资源的CPU核数

[java] view plain copy
  1. scala> var rdd = sc.parallelize(1 to 10 
  2. rdd: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[2] at parallelize at :21  
  3.    
  4. scala> rdd.collect  
  5. res3: Array[Int] = Array(12345678910)  
  6.    
  7. scala> rdd.partitions.size  
  8. res4: Int = 15  
  9.    
  10. //设置RDD为3个分区  
  11. scala> var rdd2 = sc.parallelize(1 to 10,3)  
  12. rdd2: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[3] at parallelize at :21  
  13.    
  14. scala> rdd2.collect  
  15. res5: Array[Int] = Array(12345678910)  
  16.    
  17. scala> rdd2.partitions.size  
  18. res6: Int = 3  

  • makeRDD

def makeRDD[T](seq: Seq[T], numSlices: Int = defaultParallelism)(implicit arg0: ClassTag[T]): RDD[T]

这种用法和parallelize完全相同

def makeRDD[T](seq: Seq[(T, Seq[String])])(implicit arg0: ClassTag[T]): RDD[T]

该用法可以指定每一个分区的preferredLocations。

[java] view plain copy
  1. scala> var collect = Seq((1 to 10,Seq("slave007.lxw1234.com","slave002.lxw1234.com")),  
  2. (11 to 15,Seq("slave013.lxw1234.com","slave015.lxw1234.com")))  
  3. collect: Seq[(scala.collection.immutable.Range.Inclusive, Seq[String])] = List((Range(12345678910),  
  4. List(slave007.lxw1234.com, slave002.lxw1234.com)), (Range(1112131415),List(slave013.lxw1234.com, slave015.lxw1234.com)))  
  5.    
  6. scala> var rdd = sc.makeRDD(collect)  
  7. rdd: org.apache.spark.rdd.RDD[scala.collection.immutable.Range.Inclusive] = ParallelCollectionRDD[6] at makeRDD at :23  
  8.    
  9. scala> rdd.partitions.size  
  10. res33: Int = 2  
  11.    
  12. scala> rdd.preferredLocations(rdd.partitions(0))  
  13. res34: Seq[String] = List(slave007.lxw1234.com, slave002.lxw1234.com)  
  14.    
  15. scala> rdd.preferredLocations(rdd.partitions(1))  
  16. res35: Seq[String] = List(slave013.lxw1234.com, slave015.lxw1234.com)  
指定分区的优先位置,对后续的调度优化有帮助。

从外部存储创建RDD

  • textFile

//从hdfs文件创建.

[java] view plain copy
  1. //从hdfs文件创建  
  2. scala> var rdd = sc.textFile("hdfs:///tmp/lxw1234/1.txt")  
  3. rdd: org.apache.spark.rdd.RDD[String] = MapPartitionsRDD[26] at textFile at :21  
  4.    
  5. scala> rdd.count  
  6. res48: Long = 4  
  7.    
  8. //从本地文件创建  
  9. scala> var rdd = sc.textFile("file:///etc/hadoop/conf/core-site.xml")  
  10. rdd: org.apache.spark.rdd.RDD[String] = MapPartitionsRDD[28] at textFile at :21  
  11.    
  12. scala> rdd.count  
  13. res49: Long = 97    

注意这里的本地文件路径需要在Driver和Executor端存在。

  • 从其他HDFS文件格式创建

hadoopFile

sequenceFile

objectFile

newAPIHadoopFile

  • 从Hadoop接口API创建

hadoopRDD

newAPIHadoopRDD

比如:从HBase创建RDD

[java] view plain copy
  1. scala> import org.apache.hadoop.hbase.{HBaseConfiguration, HTableDescriptor, TableName}  
  2. import org.apache.hadoop.hbase.{HBaseConfiguration, HTableDescriptor, TableName}  
  3.    
  4. scala> import org.apache.hadoop.hbase.mapreduce.TableInputFormat  
  5. import org.apache.hadoop.hbase.mapreduce.TableInputFormat  
  6.    
  7. scala> import org.apache.hadoop.hbase.client.HBaseAdmin  
  8. import org.apache.hadoop.hbase.client.HBaseAdmin  
  9.    
  10. scala> val conf = HBaseConfiguration.create()  
  11. scala> conf.set(TableInputFormat.INPUT_TABLE,"lxw1234")  
  12. scala> var hbaseRDD = sc.newAPIHadoopRDD(  
  13. conf,classOf[org.apache.hadoop.hbase.mapreduce.TableInputFormat],classOf[org.apache.hadoop.hbase.io.ImmutableBytesWritable],classOf[org.apache.hadoop.hbase.client.Result])  
  14.    
  15. scala> hbaseRDD.count  
  16. res52: Long = 1  

Action类算子和Transformation类算子

Transformations转换算子

概念:

Transformations类算子是一类算子(函数)叫做转换算子,如map,flatMap,reduceByKey等。Transformations算子是延迟执行,也叫懒加载执行

也就是说从一个RDD 转换生成另一个 RDD 的转换操作不是马上执行,需要等到有 Action 操作的时候才会真正触发运算。

 * spark转换算子
 * 1、filter

参数是函数,函数会过滤掉不符合条件的元素,返回值是新的RDD。
 * 2、sample

随机抽样算子,根据传进去的小数按比例进行又放回或者无放回的抽样。
 * 3、map

在Map中,我们会传入一个函数,该函数对每个输入都会返回一个数组(或者元组、集合)(而不是一个元素)。
 * 4、flatMap

是map的一种扩展。在flatMap中,我们会传入一个函数,该函数对每个输入都会返回一个数组或者元组、集合(而不是一个元素),然后,flatMap           把生成的多个集合(数组)“拍扁”成为一个集合(数组)或者字符串RDD。
 * 5、reduceByKey

将K、V格式的Rdd中相同的Key根据相应的逻辑进行处理。 如:单词统计的加法操作。
 * 6、distinct

没有参数,将RDD里的元素进行去重操作。
 * 7、intersection

参数是RDD,求出两个RDD的共同元素。
 * 8、subtract()

参数是RDD,将原RDD里和参数RDD里相同的元素去掉 即:返回的数据是原RDD中不和参数RDD中相同的元素。
 * 9、cartesian

参数是RDD,求两个RDD的笛卡儿积。
 * 10、sortByKey

作用在K,V格式的RDD上,对key进行升序或者降序排序.

 * 11、 mapPartiiton:

与map类似,遍历的单位是每个partition上的数据。

Spark中Key-Value型转换算子 
 * 1、join

内连接join;相当于SQL中的内关联join,只返回两个RDD根据K可以关联上的结果,join只能用于两个RDD之间的关联,如果要多个RDD关联,多关联几次即可。
 * 2、leftOuterJoin

类似于SQL中的左外关联left outer join,返回结果以前面的RDD为主,关联不上的记录为空。只能用于两个RDD之间的关联,如果要多个RDD关联,多关联几次即可。
 * 3、rightOuterJoin

类似于SQL中的有外关联right outer join,返回结果以参数中的RDD为主,关联不上的记录为空。只能用于两个RDD之间的关联,如果要多个RDD关联,多关联几次即可。

 * 4、cogroup

当调用类型(K,V)和(K,W)的数据上时,返回一个数据集(K,(Iterable<V>,Iterable<W>))
 * 5、zip

将两个RDD中的元素(KV格式/非KV格式)变成一个KV格式的RDD,两个RDD的个数必须相同。

 * 6、zipWithIndex

该函数将RDD中的元素和这个元素在RDD中的索引号(从0开始)组合成(K,V)对

Action行动算子

概念: 

Action类算子也是一类算子(函数)叫做行动算子,如foreach,collect,count等。Transformations类算子是延迟执行,Action类算子是触发执行。一个application应用程序中有几个Action类算子执行,就有几个job运行。

Action类算子

count

返回原RDD中数据的个数。

take(n)

返回一个包含数据集前n个元素的集合。

first

first=take(1),返回数据集中的第一个元素。

foreach

循环遍历数据集中的每个元素,运行相应的逻辑。

collect

返回RDD所有元素,将计算结果回收到Driver端。Note:如果数据量比较大的时候,尽量不要使用collect函数,因为这可能导致Driver端内存溢出问题。
countByValue
统计一个RDD中各个value的出现次数。返回一个map,map的key是元素的值,value是出现的次数。
countByKey
统计一个RDD中各个Key的出现次数。
reduce。
将RDD中元素两两传递给输入函数,同时产生一个新的值,新产生的值与RDD中下一个元素再被传递给输入函数直到最后只有一个值为止。

控制算子




概念:

控制算子有三种,cache,persist,checkpoint,以上算子都可以将RDD持久化,持久化的单位是partition。cache和persist都是懒执行的。必须有一个action类算子触发执行。checkpoint算子不仅能将RDD持久化到磁盘,还能切断RDD之间的依赖关系。

cache

默认将RDD的数据持久化到内存中。cache是懒执行。

注意:chche () = persist()=persist(StorgeLevel.Memory_Only)

测试cache文件:

文件:见“NASA_access_log_Aug95”文件。

测试代码:

SparkConf conf = new SparkConf();

 conf.setMaster("local").setAppName("CacheTest");

 JavaSparkContext jsc = new JavaSparkContext(conf);

 JavaRDD<String> lines = jsc.textFile("./NASA_access_log_Aug95");

 

 lines =lines.cache();

 long startTime = System.currentTimeMillis();

 long count =lines.count();

 long endTime = System.currentTimeMillis();

 System.out.println("共"+count+"条数据,"+"初始化时间+cache时间+计算时间="+(endTime-startTime));

 long countStartTime = System.currentTimeMillis();

 long countrResult =lines.count();

 long countEndTime = System.currentTimeMillis();

 System.out.println("共"+countrResult+"条数据,"+"计算时间="+ (countEndTime-countStartTime));

 jsc.stop();

persist:

可以指定持久化的级别。最常用的是MEMORY_ONLY和MEMORY_AND_DISK。”_2”表示有副本数。

持久化级别如下:


¬ cache和persist的注意事项:

1. cache和persist都是懒执行,必须有一个action类算子触发执行。

2. cache和persist算子的返回值可以赋值给一个变量,在其他job中直接使用这个变量就是使用持久化的数据了。

3. cache和persist算子后不能立即紧跟action算子。

错误:rdd.cache().count() 返回的不是持久化的RDD,而是一个数值了。

checkpoint

checkpoint将RDD持久化到磁盘,还可以切断RDD之间的依赖关系。

checkpoint 的执行原理:

1. 当RDD的job执行完毕后,会从finalRDD从后往前回溯。

2. 当回溯到某一个RDD调用了checkpoint方法,会对当前的RDD做一个标记。

3. Spark框架会自动启动一个新的job,重新计算这个RDD的数据,将数据持久化到HDFS上。

优化:对RDD执行checkpoint之前,最好对这个RDD先执行cache,这样新启动的job只需要将内存中的数据拷贝到HDFS上就可以,省去了重新计算这一步。

使用:

 SparkConf conf = new SparkConf();

 conf.setMaster("local").setAppName("checkpoint");

 JavaSparkContext sc = new JavaSparkContext(conf);

 sc.setCheckpointDir("./checkpoint");

 JavaRDD<Integer> parallelize = sc.parallelize(Arrays.asList(1,2,3));

 parallelize.checkpoint();

 parallelize.count();

 sc.stop();


代码示例:

代码流程:

/**
 * demo01 :熟悉代码的流程以及用scala实现单词统计小demo
 * Spark代码流程  
 * 1、创建SparkConf对象 设置运行模式、项目名称等信息
 * 2、创建SparkContext对象
 * 3、基于Spark上下文创建一个rdd 、对Rdd进行处理
 * 4、执行行动类算子
 * 5、关闭Spark上下文对象
 * 
 */
object Process {
   def main(args: Array[String]): Unit = {
   val conf=new SparkConf()
   conf.setMaster("local").setAppName("test")
   val sc=new SparkContext(conf);
    val lineRdd=sc.textFile("./word.txt");
    val wordRdd=lineRdd.flatMap{line => {line.split(" ")}};//读取的每行数据按照空格分割 返回的是字符串数组。然后再将字符串数组拍扁。
    val pairRdd=wordRdd.map{word => {(word,1)}}//读取每个单词然后记为1
    val reduceRdd=pairRdd.reduceByKey((v1:Int,v2:Int) =>{v1+v2})//将相同的Key执行加法操作
    reduceRdd.foreach{println}
    sc.stop()
   println("===========");
  }
}

转换算子

/**
 * demo02
 * spark转换算子
 * 1、filter:参数是函数,函数会过滤掉不符合条件的元素,返回值是新的RDD。
 * 2、sample:随机抽样算子,根据传进去的小数按比例进行又放回或者无放回的抽样。
 * 3、map:在Map中,我们会传入一个函数,该函数对每个输入都会返回一个数组(或者元组、集合)(而不是一个元素)。
 * 4、flatMap:是map的一种扩展。在flatMap中,我们会传入一个函数,该函数对每个输入都会返回一个数组或者元组、集合(而不是一个元素),然后,flatMap把生成的多个集合(数组)“拍扁”成为一个集合(数组)或者字符串RDD。
 * 5、reduceByKey:将K、V格式的Rdd中相同的Key根据相应的逻辑进行处理。 如:单词统计的加法操作。
 * 6、distinct:没有参数,将RDD里的元素进行去重操作。
 * 7、intersection:参数是RDD,求出两个RDD的共同元素。
 * 8、subtract():参数是RDD,将原RDD里和参数RDD里相同的元素去掉 即:返回的数据是原RDD中不和参数RDD中相同的元素。
 * 9、cartesian:参数是RDD,求两个RDD的笛卡儿积。
 * 10、sortByKey:作用在K,V格式的RDD上,对key进行升序或者降序排序.
 * 11、mapPartiiton:与map类似,遍历的单位是每个partition上的数据。
 * 12、groupByKey:将rdd按照key分组。
 * 13、zipWithIndex: 该函数将RDD中的元素和这个元素在RDD中的索引号(从0开始)组合成(K,V)对
 */
object NormalTransFrom {
 def main(args: Array[String]): Unit = {
   val conf=new SparkConf()
   conf.setMaster("local").setAppName("test")
   val sc=new SparkContext(conf);
   val lineRdd=sc.textFile("./data.txt");//读取的所有数据
   /**
    * 过滤出符合条件的元素,true保留,false过滤掉。
    */
   println("***************1、已进入filter方法*********************");
   val filterRdd=lineRdd.filter { line => line.equals("hello bjsxt") }//line是所有文件数据中读取的一行数据
   //line.equals("hello bjsxt") 表示:读取的一行数据为hello bjsxt的数据
   val result=filterRdd.collect();//返回RDD所有元素,将计算结果收集到Driver端
   result.foreach{
     elem => {
       println(elem);
     }
   }
   //result.foreach(println);
   println("***************filter方法结束!*********************");
   /**
    * 随机抽样算子,根据传进去的小数按比例进行又放回或者无放回的抽样。
    * 第一个参数:如果为true代表有放回的抽样,false代表无放回的抽样
    * 第二个参数代表抽样的比例
    * 第三个参数代表种子:如果对同一批数据相同种子随机抽样,那么收到的结果相同。
    * 也就是说如果前两个参数不变的情况下,设置种子值固定 那么随机抽样出的数据相同
    */
   println("***************2、已进入sample方法*********************");
   val sampleRdd=lineRdd.sample(true, 0.5)
   sampleRdd.foreach{
     println
   }
   println("***************sample方法结束!*********************");
    println("***************3、map与faltMap方法开始!*********************");
    /*map返回的是元组信息 flatMap返回的是字符串RDD*/
    val wordRdd=lineRdd.flatMap{line => {line.split(" ")}};//将读取的每行数据按空格分割,然后返回字符串数组,有多少行数据就会返回多少字符串数组,最后将所有的字符串数组进行扁平化为一个字符串RDD。
    val pairRdd=wordRdd.map{word => {(word,1)}}//遍历每个单词 然后记为1  返回的是K、V格式的元组信息
    val reduceRdd=pairRdd.reduceByKey((v1:Int,v2:Int) =>{v1+v2})//将相同key的元组 进行相加
    reduceRdd.foreach{println}
     /*map返回的是字符串数组 flatMap返回的是字符串RDD*/
     val mapResult= lineRdd.map{lines =>lines.split(" ")};//map函数执行后返回的是字符串数组RDD
     val flatMapResult= lineRdd.flatMap{lines =>lines.split(" ")};//flatMap函数执行后返回的是字符串RDD
     val result1=mapResult.collect();//collect 函数返回Array[Array[String]] result是二维数组
     result1.foreach(println); 
       /*map返回的是字符串集合 flatMap返回的是字符型集合*/
    val books = List("Hadoop","Hive","HDFS")//List[String]
    val mapResult2=books.map(s => s.toUpperCase)//List[String] = List(HADOOP, HIVE, HDFS)
    val flatMapResult2=books.flatMap(s => s.toUpperCase)//List[Char] = List(H, a, o, o, p, H, i, v, e, H, D, F, S)
    println(mapResult2);
    println("***************map与faltMap方法结束!*********************");
    println("***************4、distinct方法开始!*********************");
    val dintinctResult=lineRdd.distinct();//这里是去除相同的行
    dintinctResult.foreach {println}
    println("***************distinct方法结束!*********************");
    println("***************5、union方法开始!*********************");
    val flow = sc.parallelize(List(("String1",1),("String2",2),("String3",3)));
    val org = sc.parallelize(List(("String3",3),("String4",1),("String1",2)));
    flow.union(org);
    val u = flow.union(org);
    u.foreach(println);
     /* 输出: RDDs的union操作,把2个RDDs的元素合并起来。
      (String1,1)
      (String2,2)
      (String3,3)
      (String3,3)
      (String4,1)
      (String1,2)
    * */
    println("***************union方法结束!*********************");
     println("***************6、intersection方法开始!*********************");
   val same=flow.intersection(org);
   same.foreach(println)
    /*
     * (String3,3)
     * 
     * 
     */
   println("***************intersection方法结束!*********************");
   println("***************7、subtract方法开始!*********************");
   val different=flow.subtract(org);
   different.foreach(println)
   /*
    * (String2,2)
      (String1,1)
    */
   println("***************7、subtract方法结束!*********************");
   println("***************8、cartesian方法开始!*********************");
 
   val cartesian=flow.cartesian(org)
   cartesian.foreach(println)
   /*
((String1,1),(String3,3))
((String1,1),(String4,1))
((String1,1),(String1,2))
((String2,2),(String3,3))
((String2,2),(String4,1))
((String2,2),(String1,2))
((String3,3),(String3,3))
((String3,3),(String4,1))
((String3,3),(String1,2))
    */
   println("***************8、cartesian方法结束!*********************");
  
    println("=========9、sortByKey的使用===========")
    val mapRdd1=reduceRdd.map(tuple =>{(tuple._2,tuple._1)})//将reduceRdd的map中的key和value位置转换
    val sortRdd=mapRdd1.sortByKey()//默认升序排序  当方法参数为false时降序排序
    val mapRdd2=sortRdd.map(tuple =>{(tuple._2,tuple._1)})
    mapRdd2.foreach{println}
    println("========10、first方法的使用==========");
    val firstResult=mapRdd2.first();//返回数据集中的第一个元素。
    println("firstResult="+firstResult);
    println("========11、take(n)方法的使用==========");
    val takenResult=mapRdd2.take(2);//返回一个包含数据集前n个元素的集合。
    takenResult.foreach{
      println
    }
    println("========12、mapPartitions方法的开始==========");
    val rdd1 = sc.makeRDD(Array(1,2,3,4,5,6),3)
    val mapResults  = rdd1.mapPartitions(iter=>{
      println("插入数据库")
      iter
    })
    mapResults.foreach { println }
    println("========mapPartitions方法的结束==========");
    println("========13、groupByKey方法的开始==========");
     val rdd13 = sc.makeRDD(Array(
        (1,"a"),
        (1,"b"),
        (2,"c"),
        (3,"d")
       ))    
        
    val result13 = rdd13.groupByKey()
    result13.foreach(println)
    /*
     * (1,CompactBuffer(a, b))
     * (3,CompactBuffer(d))
     * (2,CompactBuffer(c))
     */
    println("========groupByKey方法的结束==========");
    println("========14、zipWithIndex方法的开始==========");
    val rdd14 = sc.makeRDD(Array((1,"a"),(2,"b"),(3,"c")))
    val result14 = rdd14.zipWithIndex()
    result14.foreach(println)  
   /*
    *((1,a),0)
    *((2,b),1)
    *((3,c),2)    
    */
    println("========zipWithIndex方法的结束==========");
    sc.stop()
  }
}
/**
 * Demo03 
 * Spark中Key-Value型转换算子 
 * 1、join:内连接join;相当于SQL中的内关联join,只返回两个RDD根据K可以关联上的结果,join只能用于两个RDD之间的关联,如果要多个RDD关联,多关联几次即可。
 * 2、leftOuterJoin:类似于SQL中的左外关联left outer join,返回结果以前面的RDD为主,关联不上的记录为空。只能用于两个RDD之间的关联,如果要多个RDD关联,多关联几次即可。
 * 3、rightOuterJoin:类似于SQL中的有外关联right outer join,返回结果以参数中的RDD为主,关联不上的记录为空。只能用于两个RDD之间的关联,如果要多个RDD关联,多关联几次即可。
 * 4、cogroup:当调用类型(K,V)和(K,W)的数据上时,返回一个数据集(K,(Iterable<V>,Iterable<W>))
 * 5、zip:将两个RDD中的元素(KV格式/非KV格式)变成一个KV格式的RDD,两个RDD的个数必须相同。
 */
object K_V_Transformations {
def main(args: Array[String]): Unit = {
  val conf =new SparkConf();
    conf.setMaster("local").setAppName("sparkTest01")
    val sc=new SparkContext(conf);
    //创建两个RDD
    val rdd1 = sc.parallelize(Array(("aa",1),("bb",2)))  
    val rdd2 = sc.parallelize(Array(("aa",3),("dd",1)))
    println("*************1、Join方法开始*************"); 
    val result=rdd1.join(rdd2);//(String, (Int, Int)) 内连接后的RDD是K、V格式的元组,元组的value值是元组。
    result.foreach(println)
    /**
     * (aa,(1,3))
     */
    println("*************Join方法结束*************"); 
    println("*************2、leftOuterJoin方法开始*************"); 
    var leftResult=rdd1.leftOuterJoin(rdd2);
    leftResult.foreach(println)
    /*
     * (aa,(1,Some(3)))
     * (bb,(2,None))
     */
    println("*************leftOuterJoin方法结束*************"); 
    println("*************3、rightOuterJoin方法开始*************"); 
    var rightResult=rdd1.rightOuterJoin(rdd2);
    rightResult.foreach(println)
    /*
     * (aa,(Some(1),3))
     * (dd,(None,1))
     */
    println("*************rightOuterJoin方法结束*************"); 
    println("*************4、cogroup方法开始*************"); 
    val cogroupResult=rdd1.cogroup(rdd2);
    cogroupResult.foreach(println);
      /*
     * (aa,(CompactBuffer(1),CompactBuffer(3)))
     * (dd,(CompactBuffer(),CompactBuffer(1)))
     * (bb,(CompactBuffer(2),CompactBuffer()))
     */
    println("*************cogroup方法结束*************"); 
    println("*************5、zip方法开始*************"); 
    val nameRDD  = sc.makeRDD(Array("zhangsan","lisi","wangwu"))
    val scoreRDD = sc.parallelize(Array(1,2,3))
    val zipResult = nameRDD.zip(scoreRDD)
    zipResult.foreach(println)
    /*
     * (zhangsan,1)
     * (lisi,2)
     * (wangwu,3)
     */
    println("*************zip方法结束*************"); 
  }
}

行动算子

/**
 * Demo04 行动算子
 * 1、collect:返回RDD所有元素,将计算结果回收到Driver端。
 * 2、count:返回原RDD中数据的个数。
 * 3、countByKey:统计一个RDD中各个Key的出现次数。
 * 4、countByValue:统计一个RDD中各个value的出现次数。返回一个map,map的key是元素的值,value是出现的次数。
 * 5、foreachPartition:遍历的数据是每个partition的数据。
 * 6、foreach:循环遍历数据集中的每个元素,运行相应的逻辑。
 * 7、first:返回数据集中的第一个元素。
 * 8、take:返回一个包含数据集前n个元素的集合。
 * 9、reduce:根据聚合逻辑聚合数据集中的每个元素。
 * 将RDD中元素两两传递给输入函数,同时产生一个新的值,新产生的值与RDD中下一个元素再被传递给输入函数直到最后只有一个值为止。
 * 
 */
object Action {
  def main(args: Array[String]): Unit = {
    val conf = new SparkConf()
    conf.setMaster("local").setAppName("collect")
    val sc = new SparkContext(conf)
    val lines = sc.textFile("./word.txt")
    lines.collect().foreach { println }
    val result = lines.count()
    val rdd1 = sc.parallelize(List(("a",100),("b",200), ("a",300), ("c",400)))
    val result2 = rdd1.countByKey()
    result2.foreach(println)
    
     val rdd2 = sc.makeRDD(List(
      ("a",100),    
      ("a",100),    
      ("b",300),    
      ("c",400) 
    ))
    val rdd3 = rdd2.countByValue()
    rdd3.foreach(println)
    
     val rdd4 = sc.makeRDD(Array(1,2,3,4,5))
     rdd4.foreachPartition { iter => {
     println("连接数据库。。。")
      while(iter.hasNext){
        println(iter.next())
      }
    } }
   val rdd5 = sc.makeRDD(Array(1,2,3,4,5))
   val result5 = rdd5.reduce(_+_)//根据聚合逻辑聚合数据集中的每个元素。
    println(result5)  
    
    sc.stop()
  }
}

控制算子

/**
 * cache和persist都是懒执行,必须有一个action类算子触发执行。
 * cache是吧读取的数据放到内存里
 * 而persist默认默认放在内存 但是也可以指定存放的位置
 * cache()=persist()=persist()=persist(StorageLevel..MEMORY_ONLY)
 *  cache和persist的注意事项:
 * 1.cache和persist都是懒执行,必须有一个action类算子触发执行。
 * 2.cache和persist算子的返回值可以赋值给一个变量,在其他job中直接使用这个变量就是使用持久化的数据了。
 * 3.cache和persist算子后不能立即紧跟action算子。
 * 错误:rdd.cache().count() 返回的不是持久化的RDD,而是一个数值了。
 */
object Cache {
 def main(args: Array[String]): Unit = {
    val conf = new SparkConf()
    conf.setMaster("local").setAppName("cacheTest")
    val sc = new SparkContext(conf)
    var lines = sc.textFile("./NASA_access_log_Aug95")
    lines = lines.cache()//将结果放到内存里
    val startTime = System.currentTimeMillis()
    val count = lines.count()
    val endTime = System.currentTimeMillis()
    println("共"+count +"条数据,用时"+(endTime-startTime)+"ms")//2815ms
    
    val startTime1 = System.currentTimeMillis()
    val count1 = lines.count()
    val endTime1 = System.currentTimeMillis()
    println("共"+count1 +"条数据,用时"+(endTime1-startTime1)+"ms")//84m
    
    sc.stop()
  }
}

/**
 * checkpoint将RDD持久化到磁盘,还可以切断RDD之间的依赖关系。
 */
object CheckPoint {
  def main(args: Array[String]): Unit = {
     val conf = new SparkConf()
    conf.setMaster("local").setAppName("checkpoint")
    val sc = new SparkContext(conf)
    sc.setCheckpointDir("./checkpoint")
    val lines = sc.textFile("./words.txt")
    lines.checkpoint()
    lines.foreach { println}
    sc.stop()
  }
}

原创粉丝点击