24、Spark核心编程之action操作开发实战

reduce

案例:有一个集合,里面有1到10,10个数字,现在要对10个数字进行累加
reduce操作的原理
首先将第一个和第二个元素,传入call()方法,进行计算,会获取一个结果,比如1 + 2 = 3
接着将该结果与下一个元素传入call()方法,进行计算,比如3 + 3 = 6
以此类推
所以reduce操作的本质,就是聚合,将多个元素聚合成一个元素
Java版本

public static void reduce() {
        // 创建SparkConf
        SparkConf sparkConf = new SparkConf().setAppName("reduceJava").setMaster("local");
        // 创建JavaSparkContext
        JavaSparkContext javaSparkContext = new JavaSparkContext(sparkConf);

        // 有一个集合,里面有1到10,10个数字,现在要对10个数字进行累加
        // 创建集合
        List nums = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        // 并行化集合,创建初始化RDD
        // reduce操作的原理:
        // 首先将第一个和第二个元素,传入call()方法,进行计算,会获取一个结果,比如1 + 2 = 3
        // 接着将该结果与下一个元素传入call()方法,进行计算,比如3 + 3 = 6
        // 以此类推
        // 所以reduce操作的本质,就是聚合,将多个元素聚合成一个元素
        JavaRDD numsRDD = javaSparkContext.parallelize(nums);

        Integer sum = numsRDD.reduce(new Function2() {
            @Override
            public Integer call(Integer integer, Integer integer2) throws Exception {
                return integer + integer2;
            }
        });

        System.out.println("sum = " + sum);

        // 关闭javaSparkContext
        javaSparkContext.close();
    }

scala版本

  def reduce(): Unit = {
    val conf = new SparkConf().setAppName("reduceScala").setMaster("local")
    val context = new SparkContext(conf)
    val numsRDD = context.parallelize(1 to 10)
    val sum = numsRDD.reduce(_ + _)
    println("sum = " + sum)
  }

collect

不用foreach action操作,在远程集群上遍历rdd中的元素,而使用collect操作,将分布在远程集群上的doubleNumbers RDD的数据拉取到本地
这种方式,一般不建议使用,因为如果rdd中的数据量比较大的话,比如超过1万条
那么性能会比较差,因为要从远程走大量的网络传输,将数据获取到本地
此外,除了性能差,还可能在rdd中数据量特别大的情况下,发生oom异常,内存溢出
因此,通常,还是推荐使用foreach action操作,来对最终的rdd元素进行处理
Java版本

    public static void collect() {
        // 创建SparkConf
        SparkConf sparkConf = new SparkConf().setAppName("collectJava").setMaster("local");
        // 创建JavaSparkContext
        JavaSparkContext javaSparkContext = new JavaSparkContext(sparkConf);

        // 创建集合
        List nums = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        // 并行化集合,创建初始化RDD

        JavaRDD numsRDD = javaSparkContext.parallelize(nums);

        JavaRDD doubleNumsRDD = numsRDD.map(new Function() {
            @Override
            public Integer call(Integer integer) throws Exception {
                return integer * 2;
            }
        });
        // 不用foreach action操作,在远程集群上遍历rdd中的元素,而使用collect操作,将分布在远程集群上的doubleNumbers RDD的数据拉取到本地
        // 这种方式,一般不建议使用,因为如果rdd中的数据量比较大的话,比如超过1万条
        // 那么性能会比较差,因为要从远程走大量的网络传输,将数据获取到本地
        // 此外,除了性能差,还可能在rdd中数据量特别大的情况下,发生oom异常,内存溢出
        // 因此,通常,还是推荐使用foreach action操作,来对最终的rdd元素进行处理
        List doubleNums = doubleNumsRDD.collect();
        for(Integer integer : doubleNums) {
            System.out.println("integer = " + integer);
        }

        // 关闭javaSparkContext
        javaSparkContext.close();
    }

scala版本

  def collect(): Unit = {
    val conf = new SparkConf().setAppName("collectScala").setMaster("local")
    val context = new SparkContext(conf)
    val numsRDD = context.parallelize(1 to 10)
    val doubleNumsRDD = numsRDD.map(_ * 2)
    val doubleNums = doubleNumsRDD.collect()
    for(e <- doubleNums) println("e = " + e)
  }

count

count操作,统计它有多少个元素
Java版本

    public static void count() {
        // 创建SparkConf
        SparkConf sparkConf = new SparkConf().setAppName("countJava").setMaster("local");
        // 创建JavaSparkContext
        JavaSparkContext javaSparkContext = new JavaSparkContext(sparkConf);

        // 创建集合
        List nums = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        // 并行化集合,创建初始化RDD

        JavaRDD numsRDD = javaSparkContext.parallelize(nums);
        // 对rdd使用count操作,统计它有多少个元素
        long countNum = numsRDD.count();

        System.out.println("countNum = " + countNum);

        // 关闭javaSparkContext
        javaSparkContext.close();
    }

scala版本

  def count(): Unit = {
    val conf = new SparkConf().setAppName("countScala").setMaster("local")
    val context = new SparkContext(conf)
    val numsRDD = context.parallelize(1 to 10)
    val countNumber = numsRDD.count()
    println("countNumber = " + countNumber)
  }

take

take操作,与collect类似,也是从远程集群上,获取rdd的数据,但是collect是获取rdd的所有数据,take只是获取前n个数据
Java版本

    public static void take() {
        // 创建SparkConf
        SparkConf sparkConf = new SparkConf().setAppName("takeJava").setMaster("local");
        // 创建JavaSparkContext
        JavaSparkContext javaSparkContext = new JavaSparkContext(sparkConf);

        // 创建集合
        List nums = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        // 并行化集合,创建初始化RDD

        JavaRDD numsRDD = javaSparkContext.parallelize(nums);

        // take操作,与collect类似,也是从远程集群上,获取rdd的数据
        // 但是collect是获取rdd的所有数据,take只是获取前n个数据
        List takeNumbers = numsRDD.take(5);
        for(Integer integer : takeNumbers) {
            System.out.println("integer = " + integer);
        }

        // 关闭javaSparkContext
        javaSparkContext.close();

    }

scala版本

  def take(): Unit = {
    val conf = new SparkConf().setAppName("takeScala").setMaster("local")
    val context = new SparkContext(conf)
    val numsRDD = context.parallelize(1 to 10)
    val takeNumbers = numsRDD.take(5)
    for(e <- takeNumbers) println("e = " + e)
  }

saveAsTextFile

直接将rdd中的数据,保存在HFDS文件中
但是要注意,我们这里只能指定文件夹,也就是目录
doubleNumbers.saveAsTextFile("hdfs://spark1:9000/double_number.txt");
那么实际上,会保存为目录中的/double_number.txt/part-00000文件
Java版本

    public static void saveAsTextFile() {
        // 创建SparkConf
        SparkConf sparkConf = new SparkConf().setAppName("saveAsTextFileJava");
        // 创建JavaSparkContext
        JavaSparkContext javaSparkContext = new JavaSparkContext(sparkConf);

        // 有一个集合,里面有1到10,10个数字,现在要对10个数字进行累加
        // 创建集合
        List nums = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        // 并行化集合,创建初始化RDD

        JavaRDD numsRDD = javaSparkContext.parallelize(nums);

        JavaRDD doubleNumsRDD = numsRDD.map(new Function() {
            @Override
            public Integer call(Integer integer) throws Exception {
                return integer * 2;
            }
        });

        doubleNumsRDD.saveAsTextFile("hdfs://hadoop-100:9000/doubleNumber.txt");

        // 关闭javaSparkContext
        javaSparkContext.close();

    }

scala版本

  def saveAsTextFile(): Unit = {
    val conf = new SparkConf().setAppName("saveAsTextFileScala").setMaster("local")
    val context = new SparkContext(conf)
    val numsRDD = context.parallelize(1 to 10)
    numsRDD.saveAsTextFile("hdfs://hadoop-100:9000/numsRDD")
  }

countByKey

这就是countByKey的作用,统计每个key对应的元素个数
countByKey返回的类型,直接就是Map
Java版本

public static void countByKey() {
        // 创建SparkConf
        SparkConf sparkConf = new SparkConf().setAppName("countByKeyJava").setMaster("local");
        // 创建JavaSparkContext
        JavaSparkContext javaSparkContext = new JavaSparkContext(sparkConf);

        // 创建集合
        List> scoreList = Arrays.asList(
                new Tuple2("class1", 80),
                new Tuple2("class2", 80),
                new Tuple2("class1", 95),
                new Tuple2("class2", 85)
        );
        // 并行化集合,创建初始化RDD
        JavaPairRDD scoreListRDD = javaSparkContext.parallelizePairs(scoreList);
        // 对rdd应用countByKey操作,统计每个班级的学生人数,也就是统计每个key对应的元素个数
        // 这就是countByKey的作用,统计每个key对应的元素个数
        // countByKey返回的类型,直接就是Map
        Map classNumber = scoreListRDD.countByKey();
        for (Map.Entry map : classNumber.entrySet()) {
            System.out.println(map.getKey() + "班级有" + map.getValue() + "人");
        }

        // 关闭javaSparkContext
        javaSparkContext.close();

    }

scala版本

  def countByKey(): Unit = {
    val conf = new SparkConf().setAppName("countByKeyScala").setMaster("local")
    val context = new SparkContext(conf)
    val scores = Array(("class1", 80), ("class2", 80), ("class1", 95), ("class2", 85))
    val scoreRDD = context.parallelize(scores)
    val classNumber = scoreRDD.countByKey()
    for(e <- classNumber) println(e._1 + "班级有" + e._2  + "人")
  }

foreach

foreach,遍历RDD的元素,在远程集群上执行
Java版本

    public static void foreach() {
        // 创建SparkConf
        SparkConf sparkConf = new SparkConf().setAppName("foreachJava").setMaster("local");
        // 创建JavaSparkContext
        JavaSparkContext javaSparkContext = new JavaSparkContext(sparkConf);

        // 有一个集合,里面有1到10,10个数字,现在要对10个数字进行累加
        // 创建集合
        List nums = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        // 并行化集合,创建初始化RDD

        JavaRDD numsRDD = javaSparkContext.parallelize(nums);
        numsRDD.foreach(new VoidFunction() {
            @Override
            public void call(Integer integer) throws Exception {
                System.out.println("integer = " + integer);
            }
        });

        // 关闭javaSparkContext
        javaSparkContext.close();

    }

scala版本

  def foreach(): Unit = {
    val conf = new SparkConf().setAppName("foreachScala").setMaster("local")
    val context = new SparkContext(conf)
    val numsRDD = context.parallelize(1 to 10)
    numsRDD.foreach(num => println("num = " + num))
  }

你可能感兴趣的:(24、Spark核心编程之action操作开发实战)