Spark Core学习笔记3:操作RDD--transformation、action案例

1.transformation和action介绍

  • Spark支持两种RDD操作:transformation和action

    • transformation操作会针对已有RDD创建一个新的RDD
    • action操作,主要是对RDD进行最后的操作,如遍历、reduce、保存到文件中等,并可以返回结果给Driver程序
    • 例子:map就是一种transformation操作,用于将已有RDD中的每个元素传入一个自定义的函数,并获取一个新的元素,然后将所有元素组成一个新的RDD;reduce就是一种action操作,它用于对RDD中的所有元素进行聚合操作,并获取一个最终的结果。然后返回给Driver程序
    • transformation的特点就是lazy特性。lazy特性指的是,如果一个spark应用中只定义了transformation操作,那么即使你执行该应用,这些操作也不会执行。也就是说,transformation是不会触发Spark程序的执行的,它们只是记录了对RDD所做的操作,但是不会自发的执行,只有当transformation之后,接着执行了一个action操作,那么所有的transformation才会执行。Spark通过这种lazy特性,来进行底层的spark应用执行的优化,避免产生过多中间结果
    • action的特性:action操作执行,会触发一个spark job的运行,从而触发这个action之前所有的transformation的执行

2.案例:统计文件字数

这里通过统计文件字数案例,来讲解transformation和action

  • 通过textFile()方法,针对外部文件创建了一个RDD,lines,但是实际上,程序执行到这里为止,spark.txt文件的数据是不会加载到内存中的。lines,只是代表了一个指向spark.txt文件的引用。

    val lines = sc.textFile("spark.txt")
    
  • 这里对lines RDD进行了map算子,获取了一个转换后的lineLengths RDD。但是这里连数据都没有,当然也不会做任何操作。lineLengths RDD也只是一个概念上的东西

    val lineLengths = lines.map(line => line.length)
    
  • 执行一个action操作,reduce。此时就会触发之前所有transformation操作的执行,Spark会将操作拆分成多个task到多个机器上并行执行,每个task会在本地执行map操作,并进行本地的reduce聚合,最后会进行一个全局的reduce聚合,然后将结果返回给Driver程序

    val totalLengths = lineLengths.reduce(_ + _)
    
  • 统计文本文件字数完整代码(java版)

    public class LocalFile {
    
    	public static void main(String[] args) {
    		// 创建SparkConf对象
    		SparkConf conf = new SparkConf()
    				.setAppName("LocalFile")
    				.setMaster("local");
    		// 创建SparkContext对象
    		JavaSparkContext sc = new JavaSparkContext(conf);
    		// 针对本地文件,创建初始RDD
    		JavaRDD<String> lines = sc.textFile("C:\\Users\\admin\\Desktop\\spark.txt");
    		
    		// 统计文本文件字数
    		JavaRDD<Integer> lineLengths = lines.map(new Function<String, Integer>(){
    
    			private static final long serialVersionUID = 1L;
    
    			@Override
    			public Integer call(String line) throws Exception {
    				return line.length();
    			}
    			
    		});
    		
    		int count = lineLengths.reduce(new Function2<Integer, Integer, Integer>(){
    
    			private static final long serialVersionUID = 1L;
    
    			@Override
    			public Integer call(Integer v1, Integer v2) throws Exception {
    				return v1 + v2;
    			}
    			
    		});
    		
    		System.out.println("文本文件总字数:" + count);
    		
    		// 关闭JavaSparkContext
    		sc.close();
    	}
    }
    
  • 统计文本文件字数完整代码(scala版)

    object LocalFile {
      
      def main(args: Array[String]){
        // 创建SparkConf、SparkContext
        val conf = new SparkConf().setAppName("LocalFile").setMaster("local")
        val sc = new SparkContext(conf)
        // 针对本地文件创建初始RDD
        val lines = sc.textFile("C:\\Users\\admin\\Desktop\\spark.txt", 1)
        val lineLengths = lines.map(line => line.length())
        val count = lineLengths.reduce(_ + _)
        println("文本文件总字数:" + count)
      }
    }
    

3.统计文件每行出现的次数

  • Spark有些特殊的算子,也就是特殊的transformation操作。比如groupByKey、sortByKey、reduceByKey等,其实只是针对特殊的RDD的。即包含key-value对的RDD。而这种RDD中的元素,实际上是scala中的一种类型,即Tuple2,也就是包含两个值的Tuple

  • 在scala中,需要手动导入Spark的相关隐式转换,import org.apache.spark.SparkContext._。然后,对应包含Tuple2的RDD,会自动隐式转换为PairRDDFunction,并提供reduceByKey等方法

  • 统计文件每行出现次数代码(java版)

    public class LineCount {
    
    	public static void main(String[] args) {
    		SparkConf conf = new SparkConf()
    				.setAppName("LineCount")
    				.setMaster("local");
    		JavaSparkContext sc = new JavaSparkContext(conf);
    		
    		JavaRDD<String> lines = sc.textFile("C:\\Users\\admin\\Desktop\\hello.txt");
    		
    		JavaPairRDD<String, Integer> pairs = lines.mapToPair(new PairFunction<String, String, Integer>(){
    
    			private static final long serialVersionUID = 1L;
    
    			@Override
    			public Tuple2<String, Integer> call(String line) throws Exception {
    				return new Tuple2<String, Integer>(line, 1);
    			}
    			
    		});
    		
    		JavaPairRDD<String, Integer> lineCounts = pairs.reduceByKey(new Function2<Integer, Integer, Integer>(){
    
    			private static final long serialVersionUID = 1L;
    
    			@Override
    			public Integer call(Integer v1, Integer v2) throws Exception {
    				return v1 + v2;
    			}
    			
    		});
    		
    		lineCounts.foreach(new VoidFunction<Tuple2<String,Integer>>() {
    			
    			private static final long serialVersionUID = 1L;
    
    			@Override
    			public void call(Tuple2<String, Integer> t) throws Exception {
    				System.out.println(t._1 + ": " + t._2 + " times");
    				
    			}
    		});
    		// 关闭JavaSparkContext
    		sc.close();
    	}
    }
    
    
  • 统计文件每行出现次数代码(scala版)

    object LineCount {
      
      def main(args: Array[String]){
        val conf = new SparkConf().setAppName("LineCount").setMaster("local")
        val sc = new SparkContext(conf)
        
        val lines = sc.textFile("C:\\Users\\admin\\Desktop\\hello.txt", 1)
        val pairs = lines.map(line => (line, 1))
        val lineCounts = pairs.reduceByKey(_ + _)
        
        lineCounts.foreach(lineCount => println(lineCount._1 + ": " + lineCount._2 + " times"))
      }
    }
    
    • hello.txt文件内容

      hello you
      hello me
      hello world
      hello you
      hello you
      
    • 运行结果

      hello you:3 times
      hello world:1 times
      hello me:1 times
      

4.常用transformation操作

  • map:将RDD中的每个元素传入自定义函数,获取一个新的元素,并将新的元素组成新的RDD
  • filter:对RDD中每个元素进行判断,如果返回true则保留,如果返回false则剔除。
  • flatMap:与map类似,但对每个元素都可以返回一个或多个新元素
  • groupByKey:根据key进行分组,每个key对应一个Iterable
  • reduceByKey:对每个key对应的value进行reduce操作
  • sortByKey:对每个key对应的value进行排序操作
  • join:对两个包含<key,value>对的RDD进行join操作,每个key join上的pair,都会传入自定义函数进行处理
  • cogroup:同join,但是是每个key对应的Iterable都会传入自定义函数进行处理

5.常用action操作

  • reduce:将RDD中的所有元素进行聚合操作。第一个元素与第二个元素聚合,得到的值再与第三个元素聚合,以此类推
  • collect:将RDD中所有元素获取到本地客户端
  • count:获取RDD元素总数
  • take(n):获取RDD中前n个元素
  • savaAsTextFile:将RDD元素保存到文件中,对每个元素调用toString方法
  • countByKey:对每个key对应的值进行count计数
  • foreach:遍历RDD中的每个元素
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值