[笔记迁移][Spark][4]RDD——分布式弹性数据集相关1

一、创建RDD

  1. Spark Core(代替MR,进行离线批处理操作)提供了三种创建RDD的方式:

    创建方式应用场景
    使用程序种的集合创建主要用于测试,在实际部署到集群运行之前,通过集合构造测试数据集,来测试Spark应用的流程
    使用本地文件创建主要用于临时性地处理一些存储大量数据地文件
    使用HDFS文件创建最常用地生产环境处理方式,主要可以针对HDFSs上存储地大数据进行离线批处理操作
  2. 示例
    (1) 并行化集合创建RDD => SparkContext.parallelize()
    Spark将集合中地数据拷贝到集群上去,形成一个分布式的数据集合,即一个RDD。通常来讲,集合中的部分数据会归于一个节点,而另一部分数据会归于其他节点便于并行操作。
    java实现

    	/**
    	 * 并行化集合创建RDD
    	 * 案例:累加
    	 * @author Z -Jay
    	 *
    	 */
    	public class ParallizeCollection {
    	      
    	       public static void main(String[] args) {
    	             //1. 创建SparkConf
    	            SparkConf conf = new SparkConf()
    	                                    .setAppName( "ParallizeCollection")
    	                                    .setMaster( "local");    
    	            
    	             //2. 创建JavvaSparkContext
    	            JavaSparkContext sc = new JavaSparkContext(conf );
    	            
    	             //3. 若通过并行化集合的方式创建RDD,则需要调用SparkContext及其子类的parallelize()
    	            List<Integer> numbers = Arrays. asList(1,2,3,4,5,6,7,8,9,10);
    	            JavaRDD<Integer> javaRDD = sc .parallelize(numbers);
    	            
    	             //4. 定义reduce算子操作并执行,现在执行累加:1+2=3,3+3=6;6+4=10...
    	            Integer sum=javaRDD .reduce(new Function2<Integer, Integer, Integer>() {
    	                  
    	                   private static final long serialVersionUID = 1L;
    	
    	                   @Override
    	                   public Integer call(Integer num1 , Integer num2) throws Exception {
    	                        
    	                         return num1 +num2 ;
    	                  }
    	            });
    	            
    	            System. out.println("1..10=" +sum );
    	            
    	             //4. 关闭SparkContext
    	             sc.close();
    	      }
    	}
    

    scala实现

    	class ParallelizeCollection {
      
    	  def main(args: Array[ String]){
    	     val conf = new SparkConf()
    	               .setAppName( "ParallelizeCollection")
    	               .setMaster( "local")        
    	     val sc = new SparkContext(conf)
    	     val numbers = Array( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10) 
    	     val numberRDD = sc.parallelize(numbers, 5)
    	     val sum = numberRDD.reduce(_+_)
    	     println(sum)
    	   }
    	}
    

【注】指定切割分区数,Spark会为每一个partition运行一个task来进行处理。官方建议为集群中的每个CPU创建2-4个partition。Spark默认会根据集群的情况来设置partition的数量。


(2) 本地文件和HDFS文件创建RDD => SparkContext.textFile() ==Spark支持使用“任何Hadoop存储系统即HDFS上的文件来创建RDD”,如HDFS,CASSANDRA,HBase及本地文件。==

注意事项:

  • 若只针对本地文件在Windows单机上线程模拟,则当前主机上只有一份文件即可;若针对本地文件在Spark集群上实际运行,则必须将文件拷贝到所有Worker节点上,否则报错。
  • SparkContext.textFile()支持对目录、压缩文件以及通配符进行RDD创建(即多个文件)
  • Spark会默认为HDFS上的文件的每一个Block创建一个partition,但也可以通过textFile()第二参数进行手动设置分区数量,只要比Block数量多即可,否则报错。

java实现-案例1

	/**
	 * 使用本地文件创建RDD
	 * 案例:统计文本文件字符数
	 * @author Z -Jay
	 *
	 */
	public class LetterCountLocalFile {
	      
	       public static void main(String[] args) {
	             //1. 创建SparkConf
	            SparkConf conf = new SparkConf()
	                                    .setAppName( "LetterCount")
	                                    .setMaster( "local");
	            
	             //2. 创建JavaSparkContext
	             JavaSparkContext sc = new JavaSparkContext (conf );
	            
	             //3. 使用SparkContext及其子类实现 textFile()创建文件初始RDD
	            JavaRDD<String> lines = sc.textFile("C:\\Users\\Z-Jay\\Desktop\\spark.txt" );
	            
	             //4. 统计文本文件字符数
	             //4.1 先获取每一行的长度作为元素,获取中间RDD
	            JavaRDD<Integer> lineLen = lines .map(new Function<String,Integer>(){
	
	                   private static final long serialVersionUID = 1L;
	
	                   @Override
	                   public Integer call(String line ) throws Exception {
	                         return line .length();
	                  }
	                  
	            });
	            
	             //4.2 下一阶段对中间产生的RDD元素进行累加
	            Integer count =lineLen .reduce(new Function2<Integer, Integer, Integer>() {
	                  
	                   @Override
	                   public Integer call(Integer num1 , Integer num2) throws Exception {
	                         // TODO Auto-generated method stub
	                         return num1 +num2 ;
	                  }
	            });
	            
	            System. out.println("Total count=" +count );
	            
	             //5. 关闭SparkContext
	             sc.close();
	      }
	}

scala实现-案例1

	class LetterCountLocalFile {
	 
	  def main(args:Array[String]){
	    val conf = new SparkConf(). setAppName("LetterCountHDFSFile" );
	   
	    val sc = new SparkContext( conf);
	   
	    val lines = sc.textFile("hdfs://spark1:9000/spark.txt", 1);
	 
	    val count = lines.map{ line => line.length() }
	                     . reduce(_+_)
	                    
	    println("Total count="+ count);
	  }
	 
	}

java实现-案例2

	/**
	 * 使用HDFS文件创建RDD
	 * 案例:统计文本文件字符数
	 * @author Z -Jay
	 *
	 */
	public class LetterCountHDFSFile {
	      
	       public static void main(String[] args) {
	             //1. 创建SparkConf
	             //*较本地文件方式的修改:去掉setMaster(),修改setAppName()
	            SparkConf conf = new SparkConf()
	                                    .setAppName( "HDFSFile");
	            
	             //2. 创建JavaSparkContext
	            JavaSparkContext sc = new JavaSparkContext(conf );
	            
	             //3. 使用SparkContext及其子类实现 textFile()创建文件初始RDD
	             //*修改文件路径为HDFS路径
	            JavaRDD<String> lines = sc.textFile("hdfs://spark1:9000/spark.txt" );
	            
	             //4. 统计文本文件字符数
	             //4.1 先获取每一行的长度作为元素,获取中间RDD
	            JavaRDD<Integer> lineLen = lines .map(new Function<String,Integer>(){
	
	                   private static final long serialVersionUID = 1L;
	
	                   @Override
	                   public Integer call(String line ) throws Exception {
	                         return line .length();
	                  }
	                  
	            });
	            
	             //4.2 下一阶段对中间产生的RDD元素进行累加
	            Integer count =lineLen .reduce(new Function2<Integer, Integer, Integer>() {
	                  
	                   @Override
	                   public Integer call(Integer num1 , Integer num2) throws Exception {
	                         // TODO Auto-generated method stub
	                         return num1 +num2 ;
	                  }
	            });
	            
	            System. out.println("Total count=" +count );
	            
	             //5. 关闭SparkContext
	             sc.close();
	      }
	}

scala实现-案例2

	class LetterCountLocalFile {
	 
	  def main(args :Array[String]){
	    val conf = new SparkConf().setAppName ("LetterCountHDFSFile" );
	   
	    val sc = new SparkContext(conf );
	   
	    val lines = sc.textFile("hdfs://spark1:9000/spark.txt", 1);
	 
	    val count = lines.map{ line => line.length() }
	                     . reduce(_+_)
	                    
	    println("Total count="+ count);
	  }
	}
  1. 创建RDD的其他方法
    方法说明
    SparkContext.wholeTextFiles()针对一个目录中存在的大量小文件,返回结构为<fileName,fileContent>的pair,形成一个PairRDD,非普通RDD(普通的textFile()返回的RDD中,每个元素就是文件中的一行文本)
    SparkContext.sequenceFile[K,V]()针对SequenceFile,泛型K,V即SequenceFile的Key与Value类型。K,V必须是Hadoop序列化类型(Text, LongWritable…)
    SparkContext.hadoopRDD()针对Hadoop自定义输入类型创建RDD,该方法接受JobConf,InputFormatClass,Key和Value的class
    SparkContext.objectFile()针对之前调用RDD.saveAsObject创建的序列化文件执行反序列化还原。

二、操作RDD:两类算子

  1. Transformation算子:形成Task流程

    项目说明
    概述针对已有的RDD创建一个新RDD(中间结果RDD),不会返回给Driver
    举例算子map就是典型的Transformation。将已有的RDD中每个元素传入一个自定义函数,并获取一个新元素,之后将所有新获取的元素组成一个新RDD作为下面操作的输入。
    特点懒执行Lazy
    若一个Spark应用仅定义Transformation操作,那么即使执行此应用,这些操作也不会执行。即Transformation不会触发Spark程序执行,它们与Redis事务队列化相似,只是记录了对RDD的操作流程,但不会自发的执行(没有结果的中间运算是没有意义的)。只有在定义Transformaton之后,又执行了一个Action,所有的Transformaton才会执行。 Spark正是通过这种特性,对底层的Spark应用执行优化以避免产生过多中间结果RDD。
    其他特殊的Transormation,如groupByKey, sortByKey, reduceByKey等,只针对特殊RDD,即PairRDD。这种RDD中的元素,实际上是Scala的一种类型,即Tuple2。在Scala中,需要手动导入Spark相关隐士转换,import org.apache.spark.SparkContent._。然后,对应包含Tuple2的RDD就会自动转换为PairRDDFunction,并提供reduceByKey等方法。
  2. Action算子:应用开关

    说明
    对RDD进行最后操作,如遍历/reduce/保存至文件等,且可以返回结果给Driver
    算子reduce就是典型的Action,将RDD中所有元素进行聚合,获取一个最终的结果,接着返回给Driver。
    “触发器”
    一个Action操作会执行一个SparkJob,从而按流程触发该Action之前所有的Transformation执行。
  3. Transformation类算子案例(本地模拟)
    【常用8种:map/filter/flatMap/groupByKey/reduceByKey/sortByKey/join/cogroup】

    (1) map:
    [1] 任何类型的RDD都可以调用map算子。
    [2] 在Java中,map算子接收Function对象。创建Function对象(重写call(),调用该算子的RDD中的每个元素都会传入call()中并处理返回),必须设置第二个泛型参数R即要返回的新元素类型(第一泛型参数是调用该算子的RDD元素的类型)。
    [3] 所有返回的新元素会组成一个新的RDD。
    [4] java实现-案例

           /**
           * map算子
           * 案例:将集合中每一个元素都乘2
           */
           private static void mapOp(){
                
                 //1. 创建SparkConf
                SparkConf conf = new SparkConf().setAppName("map" ).setMaster("local");
                
                 //2. 创建JavaSparkContext
                 JavaSparkContext sc = new JavaSparkContext (conf );
                
                 //3. 构建集合
                List<Integer> numbers = Arrays.asList(1,2,3,4,5);
                
                 //4. 并行化集合创建初始RDD
                JavaRDD<Integer> javaRDD = sc .parallelize(numbers);
                
                 //5. 使用map算子,将初始RDD中的每个元素都乘2
                JavaRDD<Integer> resRDD = javaRDD .map(new Function<Integer, Integer>() {
    
                       private static final long serialVersionUID = 1L;
    
                       @Override
                       public Integer call(Integer v ) throws Exception {
                             return v *2;
                      }
                });
                
                 //6. 使用foreach算子,将结果RDD的每个元素进行打印
                 resRDD.foreach(new VoidFunction<Integer>() {
                      
                       private static final long serialVersionUID = 1L;
    
                       @Override
                       public void call(Integer num) throws Exception {
                            System. out.println(num );
                      }
                });
                
                 //7. 关闭SparkContext
                 sc.close();
          }
    

    [5] scala实现-案例

       def mapOp(){
       
        val conf = new SparkConf().setAppName ("mapOp" ).setMaster ("local" ) 
        val sc = new SparkContext(conf )
        val numbers = Array(1,2,3,4,5)
        val srcRDD = sc.parallelize(numbers, 5)
        val resRDD = srcRDD.map(num => num* 2)
        resRDD.foreach( num => println(num) )
        sc.close();
      }
    }	
    

    (2) filter:
    [1] filter同样接收Function对象,只是泛型参数不同,固定为Boolean。若想在新RDD中保留该元素,则返回true,否则返回false。
    [2] java实现-案例

       /**
       * filter算子
       * 案例:过滤集合中的偶数
       */
    	private static void filterOp(){
    		            
    		             //1. 创建SparkConf
    		            SparkConf conf = new SparkConf().setAppName("filter" ).setMaster("local");
    		            
    		             //2. 创建JavaSparkContext
    		            JavaSparkContext sc = new JavaSparkContext(conf );
    		            
    		             //3. 并行化集合创建初始RDD
    		            JavaRDD< Integer> javaRDD = sc.parallelize(Arrays.asList(1,2,3,4,5,6,7,8,9,10));
    		            
    		             //4. 使用filter算子,过滤出其中偶数
    		            JavaRDD< Integer> resRDD = javaRDD.filter(new Function<Integer, Boolean>() {
    		
    		                   private static final long serialVersionUID = 1L;
    		
    		                   @Override
    		                   public Boolean call(Integer num) throws Exception {
    		                        Boolean flag=false ;
    		                         if(num %2==0)
    		                               flag=true ;
    		                         return flag ;
    		                  }
    		            });
    		            
    		             resRDD.foreach(new VoidFunction<Integer >() {
    		
    		                   private static final long serialVersionUID = 1L;
    		
    		                   @Override
    		                   public void call(Integer even ) throws Exception {
    		                        System. out.println(even );
    		                  }
    		                  
    		            });
    		            
    		             //
    		             sc.close();
    		      }
    

    [3] scala实现-案例

      def filterOp(){
       
        val conf = new SparkConf().setAppName ("filter" ).setMaster ("local" )
        val sc = new SparkContext(conf )
        val numbers = Array(1,2,3,4,5)
        val srcRDD = sc.parallelize(numbers, 5)
        val resRDD = srcRDD.filter(number => number % 2== 0)
        resRDD.foreach( even => println(even) )
        sc.close()
      }
    

    (3) flatMap
    [1] flatMap算子接收FlatMapFunction参数。其第二泛型参数U即为返回的新元素类型,call()返回的不是U,而是Iterable<U>,即返回一个包含多个元素的可迭代容器(List, Set …)。
    [2] java实现-案例

      /**
       * flatMap算子
       * 案例:将文本行拆分为多个单词
       */
       private static void flatMapOp(){
             //1. 创建SparkConf
            SparkConf conf = new SparkConf().setAppName("flatMap" ).setMaster("local");
            
             //2. 创建JavaSparkContext
            JavaSparkContext sc = new JavaSparkContext(conf );
            
             //3. 并行化集合,创建初始RDD
            JavaRDD<String> javaRDD = sc.textFile("C:\\Users\\Z-Jay\\Desktop\\spark.txt" );
            
             //4. 使用flatMap算子,将每一行文本拆分为“多个”单词
             //新的RDD中,每一个元素都是一个包含该行单词的容器迭代器
            JavaRDD<String> resRDD = javaRDD .flatMap(new FlatMapFunction<String, String>() {
    
                   private static final long serialVersionUID = 1L;
    
                   @Override
                   public Iterator<String> call(String line ) throws Exception {
                         return Arrays.asList( line.split(" ")).iterator();
                  }
                  
            });
            
             //5. 打印结果RDD
             resRDD.foreach(new VoidFunction<String>() {
    
                   private static final long serialVersionUID = 1L;
    
                   @Override
                   public void call(String word) throws Exception {
                        System. out.println(word );
                  }
                  
            });
            
             //6.关闭SparkContext
             sc.close();
      }
    

    [3] scala实现-案例

    def flatMapOp(){
    
        val conf = new SparkConf().setAppName ("flatMap" ).setMaster ("local" )
        val sc = new SparkContext(conf )
        val srcRDD = sc.textFile("C:\\ Users\\Z-Jay \\Desktop\\ spark.txt")
        val resRDD = srcRDD.flatMap(line => line.split( " "))
        resRDD.foreach( word => println(word) )
        sc.close()
    }
    

    (4) groupByKey
    [1] 只针对特殊键值对RDD——JavaPairRDD的算子,其中的元素类型为二元组Tuple。返回类型仍然是JavaPairRDD,且Key的类型不变,value类型变为之前元素的可迭代容器类型Iterable。
    [2] java实现-案例

      /**
       * groupByKey 特殊Transformation算子处理Tuple键值对
       * 案例:按班级对成绩分组
       */
       private static void groupByKeyOp(){
            
             //1. 创建SparkConf
            SparkConf conf = new SparkConf().setAppName("groupByKeyOp" ).setMaster("local");
            
             //2. 创建JavaSparkContext
            JavaSparkContext sc = new JavaSparkContext(conf );
            
             //3. 构建模拟集合,元素类型为Tuple2 二元组
            List<Tuple2<String,Integer>> scores = Arrays.asList(
                         new Tuple2<String,Integer>("class01" ,80),
                         new Tuple2<String,Integer>("class02" ,30),
                         new Tuple2<String,Integer>("class01" ,10),
                         new Tuple2<String,Integer>("class01" ,100),
                         new Tuple2<String,Integer>("class02" ,70)
                        );
            
             //4. 并行化集合,创建初始RDD,注意类型为JavaPairRDD,与Tuple2对应
            JavaPairRDD<String,Integer> javaPairRDD = sc.parallelizePairs(scores );
            
             //5. 对pairRDD的每个Tuple2元素,执行groupByKey算子,按照班级进行分组
            JavaPairRDD<String, Iterable<Integer>> groupedRDD = javaPairRDD.groupByKey();
            
             //6. 打印分组后的RDD
             groupedRDD.foreach(new VoidFunction<Tuple2<String,Iterable<Integer>>>() {
    
                   private static final long serialVersionUID = 1L;
                  
                   //遍历每一个Tuple2类型的元素,第一元素为班名字符串,第二元素为成绩的可迭代容器
                   @Override
                   public void call(Tuple2<String, Iterable<Integer>> tuple) throws Exception {
                        System. out.println("class:" +tuple ._1 );
                        
                        Iterator<Integer> iter = tuple ._2 .iterator();
                        
                         while(iter .hasNext()){
                              System. out.println(iter .next());
                        }
                        
                        System. out.println("===========================" );
                  }
            });
            
             //7. 关闭SparkContext
             sc.close();
      }
    

    [3] scala实现-案例

      def groupByKeyOp(){
    	
    	val conf = new SparkConf().setAppName ("groupByKey" ).setMaster ("local" )
    	val sc = new SparkContext(conf )
    	val scoreList = Array( Tuple2("class01" ,80 ) , Tuple2("class02", 30) , Tuple2("class01" ,10 ) , Tuple2("class01", 100) , Tuple2("class02" ,70 ) )
    	val scores = sc.parallelize(scoreList, 5)
    	val groupedSocres = scores. groupByKey()
    	groupedSocres. foreach(tuple => (
      	println(tuple_1);
      	tuple._2.foreach (score => println(score) );
      	println( "========================================" )
      ))
    }
    

    (5) reduceByKey
    [1] reduceByKey算子接收Function2对象,第一个和第二个泛型类型即为当前RDD中二元组的value类型,即调用一次call(),将传入两个连续的value值进行“聚合”。第三个泛型类型即为每一次返回结果的类型,默认与当前RDD的value类型相同。
    [2] reduceByKey算子同样返回JavaPairRDD,Tuple2<>(key,聚合结果)
    [3] java实现-案例

      /**
       * reduceByKey算子
       * 案例:统计每个班的总分
       */
       private static void reduceByKeyOp(){
            
             //1. 创建SparkConf
            SparkConf conf = new SparkConf().setAppName("reduceByKey" ).setMaster("local");
            
             //2. 创建JavaSparkContext
            JavaSparkContext sc = new JavaSparkContext(conf );
            
             //3. 构建模拟集合,元素类型为Tuple2 二元组
            List<Tuple2<String,Integer>> scores = Arrays.asList(
                         new Tuple2<String,Integer>("class01" ,80),
                         new Tuple2<String,Integer>("class02" ,30),
                         new Tuple2<String,Integer>("class01" ,10),
                         new Tuple2<String,Integer>("class01" ,100),
                         new Tuple2<String,Integer>("class02" ,70)
                        );
            
             //4. 并行化集合,创建初始RDD,注意类型为JavaPairRDD,与Tuple2对应
            JavaPairRDD<String,Integer> pairRDD = sc.parallelizePairs(scores );
            
             //5. 对pairRDD的每个Tuple2元素,执行reduceByKey算子,按照班级进行累加
            JavaPairRDD<String,Integer> pairRDD2 = pairRDD.reduceByKey(new Function2<Integer, Integer, Integer>() {
                  
                   private static final long serialVersionUID = 1L;
    
                   @Override
                   public Integer call(Integer val1 , Integer val2) throws Exception {
                         return val1 +val2 ;
                  }
            });
            
             //6. 打印结果RDD
             pairRDD2.foreach(new VoidFunction<Tuple2<String,Integer>>() {
    
                   private static final long serialVersionUID = 1L;
    
                   @Override
                   public void call(Tuple2<String, Integer> tuple) throws Exception {
                        System. out.println("class " +tuple ._1 +"'s total:"+tuple._2);
                        
                  }
                  
            });
            
             //7. 关闭SparkContext
             sc.close();
      }
    

    [4] scala实现-案例

        def reduceByKeyOp(){
    	
    	val conf = new SparkConf().setAppName ("reduceByKey" ).setMaster ("local" )
    	val sc = new SparkContext(conf )
    	val scoreList = Array( Tuple2("class01" ,80 ) , Tuple2("class02", 30) , Tuple2("class01" ,10 ) , Tuple2("class01", 100) , Tuple2("class02" ,70 ) 
    	val scores = sc.parallelize(scoreList, 5)
    	val groupedSocres = scores. reduceByKey(_+_)
    	groupedSocres. foreach(tuple => println( "class "+tuple_1)+"'s score:" +tuple._2)
    }
    

    (6) sortByKey
    [1] java实现-案例

    	  /**
           * sortByKey算子
           * 案例:按照学生分数进行排序
           */
           private static void sortByKey(){
                 //1. 创建SparkConf
                SparkConf conf = new SparkConf().setAppName("sortByKey" ).setMaster("local");
                
                 //2. 创建JavaSparkContext
                JavaSparkContext sc = new JavaSparkContext(conf );
                
                 //3. 构建模拟集合,元素类型为Tuple2 二元组
                List<Tuple2<Integer,String>> scores = Arrays.asList(
                             new Tuple2<Integer,String>(80,"tom-z" ),
                             new Tuple2<Integer,String>(30,"tom-x" ),
                             new Tuple2<Integer,String>(80,"tom" ),
                             new Tuple2<Integer,String>(60,"amy" ),
                             new Tuple2<Integer,String>(100,"fiona" )
                            );
                
                 //4. 并行化集合,创建初始RDD,注意类型为JavaPairRDD,与Tuple2对应
                JavaPairRDD<Integer,String> pairRDD = sc.parallelizePairs(scores );
                
                 //5. 对pairRDD执行sortByKey算子,按照成绩进行排序,默认升序,指定为false则降序
                JavaPairRDD<Integer,String> pairRDD2 = pairRDD.sortByKey(false);
                
                 //6. 打印结果RDD
                 pairRDD2.foreach(new VoidFunction<Tuple2<Integer,String>>() {
    
                       private static final long serialVersionUID = 1L;
    
                       @Override
                       public void call(Tuple2<Integer, String> tuple) throws Exception {
                            System. out.println("score "+tuple._1+":"+ tuple._2 );
                      }
                });
                
                 //7. 关闭SparkContext
                 sc.close();
          }
    

    [2] scala实现-案例

        def sortByKey(){
        
            val conf = new SparkConf ().setAppName ("sortByKey" ).setMaster ("local" )
        	val sc = new SparkContext(conf )
    		val scoreList = Array( Tuple2(80 ,"tom-z" ) , Tuple2(30,"tom-x") , Tuple2(80 ,"tom" ) , Tuple2(60,"amy") , Tuple2(100 ,"fiona" ) )
    		val scores = sc.parallelize(scoreList, 5)
    		val sortedScores = scores. sortByKey()
    		sortedSocres.foreach (tuple => println(tuple._1+":" +tuple._2)
    	 }
    

    (7) 高级算子join
    [1] join算子由一个JavaPairRDD调用,接收一个JavaPairRDD为参数。根据key实现SQL中的join功能,返回连接后的结果,返回的类型为JavaPairRDD,其元素形式为Tuple2<共用键,Tuple2<调用RDD中的值,参数RDD中的值>>。
    [2] java实现-案例

      /**
       * join算子
       * 案例:打印学生成绩
       */
       private static void joinOp(){
             //1. 创建SparkConf
            SparkConf conf = new SparkConf().setAppName("join" ).setMaster("local");
            
             //2. 创建JavaSparkContext
            JavaSparkContext sc = new JavaSparkContext(conf );
            
             //3. 构建模拟集合
            List<Tuple2<Integer,String>> stuList = Arrays.asList(
                         new Tuple2<Integer,String>(1,"tom-z" ),
                         new Tuple2<Integer,String>(2,"tom-x" ),
                         new Tuple2<Integer,String>(3,"tom" ),
                         new Tuple2<Integer,String>(4,"amy" ),
                         new Tuple2<Integer,String>(5,"fiona" )
                        );
            
            List<Tuple2<Integer,Integer>> scoreList = Arrays.asList(
                         new Tuple2<Integer,Integer>(1,80),
                         new Tuple2<Integer,Integer>(2,30),
                         new Tuple2<Integer,Integer>(3,70),
                         new Tuple2<Integer,Integer>(4,60),
                         new Tuple2<Integer,Integer>(5,100)
                        );
            
             //4. 并行化集合,创建两个RDD
            JavaPairRDD<Integer,String> students = sc.parallelizePairs(stuList );
            JavaPairRDD<Integer, Integer> scores = sc.parallelizePairs(scoreList );
            
             //5. 对两个pairRDD执行join算子,执行类似SQL JOIN的操作
            JavaPairRDD<Integer, Tuple2<String, Integer>> resRDD = students.join(scores );
            
             //6.打印结果RDD
             resRDD.foreach(new VoidFunction<Tuple2<Integer,Tuple2<String,Integer>>>() {
    
                   private static final long serialVersionUID = 1L;
    
                   @Override
                   public void call(Tuple2<Integer, Tuple2<String, Integer>> tuple) throws Exception {
                         System.out.println( "student id: "+tuple ._1 );
                         System.out.println( "student name:"+tuple ._2 ._1 );
                         System.out.println( "student score:"+tuple._2._2);
                        
                  }
            });
            
             //7. 关闭SparkContext
             sc.close();
      }
    

    [3] scala实现-案例

        def joinOp(){
    	val conf = new SparkConf().setAppName ("join" ).setMaster ("local" )
    	val sc = new SparkContext(conf )
    	val stuList = Array( Tuple2( 1, "tom-z") , Tuple2 (2 ,"tom-x" ) , Tuple2(3,"tom") , Tuple2(4 ,"amy" ) , Tuple2(5,"fiona") )
    	val scoreList = Array( Tuple2(1 ,80 ) , Tuple2(2,70) , Tuple2( 3, 60) , Tuple2(4 ,50 ) , Tuple2(5,100) )
    	val stus = sc.parallelize(stuList, 5)
    	val scores = sc.parallelize(scoreList, 5)
    	val resRDD = stus.join(scores)
        resRDD.foreach(tuple => (
          println( "student id"+tuple._1);
          println( "student name "+tuple._2._1)
          println( "student score "+tuple._2._2)
     ))
    }
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值