Spak基础—4、RDD和DataSet的API(JAVA)

1、RDD的API

RDD的使用主要分转换操作和动作操作,其中转换操作输入值是RDD,返回值是RDD,且其是惰性的,也就是说不会真的去操作,只有当动作操作到来时才会全部一次性去操作类似于链条一样。动作操作的输入值是RDD,输出值的值,也就是RDD操作的终结。

1-0、创建RDD
/*
*创建rdd的方式有多种
*从文件读取、从数据源获取、手动创建
*步骤都是:
*	1、创建sparkconf进行配置
*	2、创建JavaSparkContext
*	3、创建JavaRDD
*注意:SparkSession是用在SparkSQL、SparkStreaming上
*/
//1、手动创建
	SparkConf conf = new SparkConf();
    JavaSparkContext sc = new JavaSparkContext("local", "First Spark App", conf);
    ArrayList<String> list = new ArrayList<String>();
    list.add("张三");
    list.add("李四");
    list.add("王五");
    list.add("王五");
    JavaRDD<String> javaRDD = sc.parallelize(list);
//2、从文件读取
    SparkConf conf = new SparkConf();
    JavaSparkContext sc = new JavaSparkContext("local", "First Spark App", conf);
    JavaRDD<String> javaRDD= sc.textFile("D://ab.txt");
//3、从数据源获取
    SparkConf conf = new SparkConf();
    JavaSparkContext sc = new JavaSparkContext("local", "First Spark App", conf);
    JavaRDD<String> javaRDD= sc.textFile("HDFS的路径");
1-1、转换算子
  • map操作

            //针对普通的rdd
            JavaRDD<String> maprdd = javaRDD.map(x -> {
                return x + "哈哈";
            });
            loger.info(String.valueOf(maprdd.collect()));
    结果:
        [张三哈哈, 李四哈哈, 王五哈哈, 王五哈哈]
        
        	//针对键值对RDD,也就是pair RDD
        		//首先创建key:value的规则
            PairFunction<String,String,Integer> keyData = (String x)->{return new Tuple2(x,1);};
                //创建JavaPairRdd也就是键值对RDD
            JavaPairRDD<String,Integer> javaPairRDD = javaRDD.mapToPair(keyData);
            loger.info(String.valueOf(javaPairRDD.collect()));
        	
    结果:
         [(张三,1), (李四,1), (王五,1), (王五,1)]
        
    注意:
        PairFunction<String,String,Integer> keyData = (String x)->{return new Tuple2(x,1);}; 使用了函数式编程
        原生应该是这样:
            PairFunction<String, String, Integer> keyData = new PairFunction<String, String, Integer>() {
            	 public Tuple2<String, Integer> call(String x) {
                 	return new Tuple2(x, 1);
             	}
        	};
                
    //JavaPairRDD适用的算子是:各种聚合操作,比如reduceBykey,groupBykey,combineBykey,mergeBykey,sortBykey()等
    
  • flatmap算子

    /*
    *flatmap算子的功能是对每一个值进行map然后再进行扁平化。说白了就是进行map,然后汇总一下
    *比如map产生的是[[1,2],[3,4]] 
    *那么flatmap就会将其扁平化成[1,2,3,4],就是汇聚成一个整体
    */
    	    SparkConf conf = new SparkConf();
            JavaSparkContext sc = new JavaSparkContext("local", "First Spark App", conf);
            ArrayList<String> list = new ArrayList<String>();
            list.add("张_三");
            list.add("李_四");
            list.add("王_五");
            list.add("王_五");
    //map的结果是:
    	    JavaRDD<String> javaRDD = sc.parallelize(list);
            JavaRDD<List<String>> map = javaRDD.map(x -> {
                return Arrays.asList(x.split("_"));
            });
            loger.info(String.valueOf(map.collect()));
     [[,], [,], [,], [,]]
    //进行flatmap的结果是:
            JavaRDD<String> flatmap = javaRDD.flatMap(new FlatMapFunction<String, String>() {
                @Override
                public Iterator<String> call(String s) throws Exception {
                    return Arrays.asList(s.split("_")).iterator();
                }
            });
            loger.info("flatmap结果如下----------------------------");
            loger.info(String.valueOf(flatmap.collect()));
    结果如下:
        [,,,,,,,]
    		
    
    
  • filter算子:

    /*
    *filter算子的作用就是过滤,只保留符合函数定义的条件
    */
            JavaRDD<String> filtermap = javaRDD.filter(x -> {
                return !x.equals("张_三");
            });
            loger.info(String.valueOf(filtermap.collect()));
    结果:
        [李_四, 王_五, 王_五]
    
  • groupBykey(针对pair RDD)

    /*
    *groupBykey针对pair RDD,进行聚合
    */
            SparkConf conf = new SparkConf();
            JavaSparkContext sc = new JavaSparkContext("local", "First Spark App", conf);
            ArrayList<String> list = new ArrayList<String>();
            list.add("张_三");
            list.add("李_四");
            list.add("王_五");
            list.add("王_五");
    		//首先创建key:value的规则
            PairFunction<String,String,Integer> keyData = (String x)->{return new Tuple2(x,1);};
            //创建JavaPairRdd也就是键值对RDD
            JavaPairRDD<String,Integer> javaPairRDD = javaRDD.mapToPair(keyData);
            //4、groupbyKey算子(针对pair RDD)
    
            JavaPairRDD<String, Iterable<Integer>> stringIterableJavaPairRDD = javaPairRDD.groupByKey();
            loger.info(String.valueOf(stringIterableJavaPairRDD.collect()));
    
    结果:
        [(张_三,[1]), (李_四,[1]), (王_五,[1, 1])]
    
  • reduceBykey(针对pair RDD)

    /*
    *reduceBykey针对pair RDD,进行汇总
    */
            SparkConf conf = new SparkConf();
            JavaSparkContext sc = new JavaSparkContext("local", "First Spark App", conf);
            ArrayList<String> list = new ArrayList<String>();
            list.add("张_三");
            list.add("李_四");
            list.add("王_五");
            list.add("王_五");
    		//首先创建key:value的规则
            PairFunction<String,String,Integer> keyData = (String x)->{return new Tuple2(x,1);};
            //创建JavaPairRdd也就是键值对RDD
            JavaPairRDD<String,Integer> javaPairRDD = javaRDD.mapToPair(keyData);
            //4、reduceBykey算子(针对pair RDD)
    
            JavaPairRDD<String, Integer> reduceByKeyRdd = javaPairRDD.reduceByKey((x,y)->{return x+y;});
            loger.info(String.valueOf(reduceByKeyRdd.collect()));
    
    结果:
       [(张_三,1), (李_四,1), (王_五,2)]
        
     注意:
        reduceBykey与groupBykey的区别在于reduceBykey最终每一个key的value是按照规则汇总的值,而groupBykey就只是单纯的聚合在一起
    
  • 集合运算-union算子

    /*
    *union算子的作用就是将两个rdd合成一个rdd
    */
            SparkConf conf = new SparkConf();
            JavaSparkContext sc = new JavaSparkContext("local", "First Spark App", conf);
            ArrayList<String> list = new ArrayList<String>();
            list.add("张_三");
            list.add("李_四");
            list.add("王_五");
            list.add("王_五");
            loger.info("任务开始");
            loger.info(String.valueOf(list));
            JavaRDD<String> javaRDD = sc.parallelize(list);
    
            ArrayList<String> list2 = new ArrayList<String>();
            list2.add("张_三_2");
            list2.add("李_四_2");
            list2.add("王_五_2");
            list2.add("王_五_2");
            JavaRDD<String> javaRDD2 = sc.parallelize(list2);
            JavaRDD<String> union = javaRDD.union(javaRDD2);
            loger.info(String.valueOf(union.collect()));
    
    结果:
        [张_三, 李_四, 王_五, 王_五, 张_三_2, 李_四_2, 王_五_2, 王_五_2]
    
  • 集合运算-subtract 算子

    /*
    *subtract 算子是 rdd1减去rdd2中rdd1有的 也就是 rdd1-(rdd1交rdd2) 比如rdd1 = [1,2,3] *rdd2=[2,3,4,5] 则rdd1.subtract(rdd2) 就是[1]
    */
            SparkConf conf = new SparkConf();
            JavaSparkContext sc = new JavaSparkContext("local", "First Spark App", conf);
            ArrayList<String> list = new ArrayList<String>();
            list.add("张_三");
            list.add("李_四");
            list.add("王_五");
            list.add("王_五");
            loger.info("任务开始");
            loger.info(String.valueOf(list));
            JavaRDD<String> javaRDD = sc.parallelize(list);
    
            ArrayList<String> list2 = new ArrayList<String>();
            list2.add("张_三_2");
            list2.add("李_四");
            list2.add("王_五_2");
            list2.add("王_五_2");
    	    JavaRDD<String> javaRDD2 = sc.parallelize(list2);
            JavaRDD<String> subtract = javaRDD.subtract(javaRDD2);
            loger.info(String.valueOf(subtract.collect()));
    
    结果是:
        [王_五, 王_五, 张_三]
    
  • 集合运算-intersection算子

    /*
    *intersection算子就是取rdd1与rdd2的交集
    */
            SparkConf conf = new SparkConf();
            JavaSparkContext sc = new JavaSparkContext("local", "First Spark App", conf);
            ArrayList<String> list = new ArrayList<String>();
            list.add("张_三");
            list.add("李_四");
            list.add("王_五");
            list.add("王_五");
            loger.info("任务开始");
            loger.info(String.valueOf(list));
            JavaRDD<String> javaRDD = sc.parallelize(list);
    
            ArrayList<String> list2 = new ArrayList<String>();
            list2.add("张_三_2");
            list2.add("李_四");
            list2.add("王_五_2");
            list2.add("王_五_2");
    	    JavaRDD<String> javaRDD2 = sc.parallelize(list2);
            JavaRDD<String> subtract = javaRDD.intersection(javaRDD2);
            loger.info(String.valueOf(subtract.collect()));
    
    结果:
        [李_四]
    
  • join操作(Pair RDD)

     /*
     *join的操作就是将两个键值对rdd进行连接,join就是nature join 当然还有*left join、right join、cartesian也就是笛卡尔积
     */
    		SparkConf conf = new SparkConf();
            JavaSparkContext sc = new JavaSparkContext("local", "First Spark App", conf);
            ArrayList<String> list = new ArrayList<String>();
            list.add("张_三");
            list.add("李_四");
            list.add("王_五");
            list.add("王_五");
            loger.info("任务开始");
            loger.info(String.valueOf(list));
            JavaRDD<String> javaRDD = sc.parallelize(list);
    
                //首先创建key:value的规则
            PairFunction<String,String,Integer> keyData = (String x)->{return new Tuple2(x,1);};
                //创建JavaPairRdd也就是键值对RDD
            JavaPairRDD<String,Integer> javaPairRDD = javaRDD.mapToPair(keyData);
    		//创建规则2
            PairFunction<String,String,Integer> keyData2 = (String x)->{return new Tuple2(x,2);};
    		//创建JavaPairRdd2也就是键值对RDD
            JavaPairRDD<String,Integer> javaPairRDD2 = javaRDD.mapToPair(keyData2);
    
            JavaPairRDD<String, Tuple2<Integer, Integer>> join = javaPairRDD.join(javaPairRDD2);
            loger.info(String.valueOf(join.collect()));
    
    结果:
        [(张_三,(1,2)), (李_四,(1,2)), (王_五,(1,2)), (王_五,(1,2)), (王_五,(1,2)), (王_五,(1,2))]
        
        过程就是
        rdd1	  rdd2
        张_三 1   张_三 2
        李_四 1	李_四 2
        王_五 1	王_五 2
        王_五 1	王_五 2
        
        最后就是
        	(张_三,(1,2))
        	(李_四,(1,2))
        	(王五,(rdd1第一个王_五的1,rdd2第一个王_五的2))
            (王五,(rdd1第一个王_五的1,rdd2第二个王_五的2))
            (王五,(rdd1第二个王_五的1,rdd2第一个王_五的2))
            (王五,(rdd1第二个王_五的1,rdd2第二个王_五的2))
    
1-2、动作算子
  • collect算子:获取所有的值(以列表形式返回)

  • take(n)算子:获取前n个内容(以列表形式返回)

            SparkConf conf = new SparkConf();
            JavaSparkContext sc = new JavaSparkContext("local", "First Spark App", conf);
            ArrayList<String> list = new ArrayList<String>();
            list.add("张_三");
            list.add("李_四");
            list.add("王_五");
            list.add("王_五");
            loger.info("任务开始");
            loger.info(String.valueOf(list));
            JavaRDD<String> javaRDD = sc.parallelize(list);
            //动作算子
            //1、take(n)算子
            List<String> take = javaRDD.take(2);
            loger.info(String.valueOf(take));
    
    结果:
        [张_三, 李_四]
    
  • count()算子:获取所有的个数

  • reduce算子:

    /*
    *reduce算子的作用就是整体进行聚合,返回一个数值,与reduceBykey不同的是,*reduceBykey其实就是按key进行分组然后reduce。
    */
            SparkConf conf = new SparkConf();
            JavaSparkContext sc = new JavaSparkContext("local", "First Spark App", conf);
            ArrayList<String> list = new ArrayList<String>();
            list.add("张_三");
            list.add("李_四");
            list.add("王_五");
            list.add("王_五");
            loger.info("任务开始");
            loger.info(String.valueOf(list));
            JavaRDD<String> javaRDD = sc.parallelize(list);
            //2、reduce算子
            String reduce = javaRDD.reduce((x, y) -> {
                return x + y+"|";
            });
            loger.info(reduce);
    
    结果:
        张_三李_四|王_五|王_五|
    
  • foreach算子

    /*
    *相较于前者action算子的返回一个值、返回一个集合相比,foreach不会返回值,*作用就是对每一个元素进行相关操作
    */
            SparkConf conf = new SparkConf();
            JavaSparkContext sc = new JavaSparkContext("local", "First Spark App", conf);
            ArrayList<String> list = new ArrayList<String>();
            list.add("张_三");
            list.add("李_四");
            list.add("王_五");
            list.add("王_五");
            loger.info("任务开始");
            loger.info(String.valueOf(list));
            JavaRDD<String> javaRDD = sc.parallelize(list);
            javaRDD.foreach(x->{
                System.out.println(x);
            });
    结果:
        就是对rdd的每一个值进行打印操作
        张_三
        李_四
        王_五
        王_五
        
    
  • foreachpartition

    /*
    *foreachpartition方法的作用就是对每一个分区进行操作,在函数内部,通过迭
    *代器的方式,对分区的每一个元素进行操作
    */
            SparkConf conf = new SparkConf();
            JavaSparkContext sc = new JavaSparkContext("local", "First Spark App", conf);
            ArrayList<String> list = new ArrayList<String>();
            list.add("张_三");
            list.add("李_四");
            list.add("王_五");
            list.add("王_五");
            loger.info("任务开始");
            loger.info(String.valueOf(list));
            JavaRDD<String> javaRDD = sc.parallelize(list);
    
            javaRDD.foreachPartition(new VoidFunction<Iterator<String>>() {
                @Override
                public void call(Iterator<String> stringIterator) throws Exception {
                    while (stringIterator.hasNext()){
                        String x= stringIterator.next();
                        System.out.println(x);
                    }
                }
            });
    
    结果如下:这个时候还没有划分分区,所以只有一个主分区
        张_三
        李_四
        王_五
        王_五
    
1-3、其他操作

​ 除了上述的转换和动作算子之外,为了效率的提高,可以使用如下相关操作。

  • 持久化操作:

    持久化操作的目的是,为了减少计算次数,优化执行效率。因为spark的计算引擎,默认的是:每次进行一次rdd操作时,都会重新进行一次从源头到这个rdd的过程,再进行你要执行的操作,所以效率很低。持久化的作用就是,将你需要复用的rdd保存到内存或磁盘中,下次使用直接就可以使用了,无需再执行一遍获取此rdd的过程,极大的提高了效率。但是也有可能导致资源不足,具体见RDD优化策略。

    • cache操作

      /*
      *cache的操作,就是将rdd持久化到内存中,供之后复用。但只有触发action时才会进行保存,所以建议count一下,保存一下数据
      */
              SparkConf conf = new SparkConf();
              JavaSparkContext sc = new JavaSparkContext("local", "First Spark App", conf);
              ArrayList<String> list = new ArrayList<String>();
              list.add("张_三");
              list.add("李_四");
              list.add("王_五");
              list.add("王_五");
              loger.info("任务开始");
              loger.info(String.valueOf(list));
              JavaRDD<String> javaRDD = sc.parallelize(list);
              //1、cache操作
                      JavaRDD<String> filtermap = javaRDD.filter(x -> {
                  return !x.equals("张_三");
              });
      		filtermap.cache().count();
      
      作用:这个就是将filtermap保存到了内存中,以后再使用filtermap就不会根据链路重新执行一次获取filtermap的操作了
      
      
    • peisist操作

      /*
      *persist操作,就是将数据持久化到指定的区域,cache其实是persist的一种,就是全部持久化到内存的一种
      *persist的种类包括:MEMORY_ONLY(就是cache)、MEMORY_AND_DISK、*MEMORY_ONLY_SER、MEMORY_AND_DISK_SER、DISK_ONLY、*MEMORY_ONLY_2、MEMORY_AND_DISK_2
      *同样需要触发action才能真的执行,所以建议count一下,持久化一下
      */
              SparkConf conf = new SparkConf();
              JavaSparkContext sc = new JavaSparkContext("local", "First Spark App", conf);
              ArrayList<String> list = new ArrayList<String>();
              list.add("张_三");
              list.add("李_四");
              list.add("王_五");
              list.add("王_五");
              loger.info("任务开始");
              loger.info(String.valueOf(list));
              JavaRDD<String> javaRDD = sc.parallelize(list);
              //1、cache操作
                      JavaRDD<String> filtermap = javaRDD.filter(x -> {
                  return !x.equals("张_三");
              });
      		filtermap.persist(StorageLevel.MEMORY_AND_DISK()).count();
      结果:
          持久化到了内存和磁盘中,也就是内存不够时,会持久化到磁盘。
      
    • unpersist操作

      /*
      *unpersist功能就是移除持久化
      */
              SparkConf conf = new SparkConf();
              JavaSparkContext sc = new JavaSparkContext("local", "First Spark App", conf);
              ArrayList<String> list = new ArrayList<String>();
              list.add("张_三");
              list.add("李_四");
              list.add("王_五");
              list.add("王_五");
              loger.info("任务开始");
              loger.info(String.valueOf(list));
              JavaRDD<String> javaRDD = sc.parallelize(list);
              //1、cache操作
                      JavaRDD<String> filtermap = javaRDD.filter(x -> {
                  return !x.equals("张_三");
              });
      		filtermap.persist(StorageLevel.MEMORY_AND_DISK()).count();
              //3、unpersist操作
               filtermap.unpersist();
      
  • 手动分区,在连接时,聚合时更快,可以获益的操作是:groupWith()、join()、leftOuterJoin()、rightOuterJoin()、groupByKey()、reduceByKey()、 combineByKey() 以及 lookup()。

2、DataSet的API

DataSet是结构化的数据集合,包括强类型和弱类型,其中DataFrame是DataSet的一种即DataSet是弱类型,每行数据都是一个Row对象。除了DataFrame即DataSet之外,DataSet<类名称>,可以知道每一条数据的每一个属性的数据类型,是强类型。

DataSet本质还是RDD,拥有RDD的优点以及算子特点(Transform转换算子是惰性的遇到Action动作算子才生效)可以与RDD相互转换。DataSet可以进行SparkSQL操作,可以方便操作表。

2-1、DataSet与DataFrame以及RDD的不同点

DataSet与RDD的不同点在于:

  • DataSet不同于RDD,没有使用Java序列化器或Kryo进行序列化,而是采用一种特殊的编码器进行序列化,这种序列化的好处是在很多操作比如filter、sort等不用再反序列化,减少了频繁序列化和反序列化的消耗。
  • DataSet可以直接进行SparkSQL操作

DataFrame与DataSet区别:

  • DataFrame是DataSet的特殊的一种即DataSet,因此DataSet是强类型的,DataFrame是弱类型的
  • DataFrame不是编译时类型安全的即编译时不会检测类型(Row是弱类型),DataSet是编译时类型安全的即由强类型的JVM Object组成。

DataFrame与RDD的区别:

  • DataFrame的前身是SchemaRDD不继承RDD,自己实现了RDD的大部分功能,可以转换成RDD
  • DataFrame有比RDD更多的算子,且可以根据执行计划优化
  • DataFrame有Schema即结构内容,通过Schema就可以读懂数据,因此只需要序列化和反序列化数据即可(Schema不参与序列化)
2-2、转换算子
  • map算子

    //基础map
    /*
    *map算子的含义就是对Dataset集中的每一个元素都进行操作,也就是每一个元素经过操作后返回新的元素
    */
    //下面的程序含义就是将Dataset ds中的每一个值通过map计算出其长度,返回新的dataset
    public class TestSparkJava {
        public static void main(String[] args) {
            SparkSession spark = SparkSession.builder().master("local[2]").appName("DataSetEncoderExample").getOrCreate();
            List<String> data = Arrays.asList("chen", "li", "huang");
            //创建dataset
            Dataset<String> ds = spark.createDataset(data, Encoders.STRING());
            //转换算子
            //1、map算子
            Dataset<Integer> map = ds.map(new MapFunction<String, Integer>() {
                @Override
                public Integer call(String v) throws Exception {
                    return v.length();
                }
            }, Encoders.INT());
            map.show();
        }
    }
    
    //结果如下:
    +-----+
    |value|
    +-----+
    |    4|
    |    2|
    |    5|
    +-----+
    /*
    *其中,MapFunction<String, Integer>函数表示输入的类型和输出的类型
    *Encoders.INT()表示最后要生成的类型,也就是显示转换
    */
        
    //当然map也可以将每一个值转换成自己的数据类型,也就是对象
    //首先,对象:
        public class Bike implements Serializable {
        private static final long serialVersionUID = 1L;
        private String bike_type;
        private int bike_money;
    
    
        public String getBike_type() {
            return bike_type;
        }
    
        public void setBike_type(String bike_type) {
            this.bike_type = bike_type;
        }
    
        public int getBike_money() {
            return bike_money;
        }
    
        public void setBike_money(int bike_money) {
            this.bike_money = bike_money;
        }
    
        public Bike(String bike_type, int bike_money) {
            this.bike_type = bike_type;
            this.bike_money = bike_money;
        }
    }
    
    //转换成对象的代码如下
    public class TestSparkJava {
        public static void main(String[] args) {
            SparkSession spark = SparkSession.builder().master("local[2]").appName("DataSetEncoderExample").getOrCreate();
            List<String> data = Arrays.asList("chen", "li", "huang");
    
            //创建dataset
            Dataset<String> ds = spark.createDataset(data, Encoders.STRING());
    
            //转换算子
            //1、map算子
            //1-2高级map
            Encoder<Bike> bikeEncoders = Encoders.kryo(Bike.class);
            Dataset<Bike> map = ds.map(new MapFunction<String, Bike>() {
                @Override
                public Bike call(String s) throws Exception {
                    return new Bike(s, s.length());
                }
            }, bikeEncoders);
            map.show();	
        }
    }
    //结果
    +--------------------+
    |               value|
    +--------------------+
    |[01 00 63 6F 6D 2...|
    |[01 00 63 6F 6D 2...|
    |[01 00 63 6F 6D 2...|
    +--------------------+
    /*
    *其中,Encoder<Bike> bikeEncoders = Encoders.kryo(Bike.class);就是创建在显示转型时的类型
    *打印的是对象的字节码,但是效果已经达到了,可以供给之后使用
    */
    
  • flatmap

  • mapPartitions

  • filter算子

    /*
    *filter算子的作用就是根据某一条件进行过滤,返回的仍然是Dataset
    */
    public class TestSparkJava {
        public static void main(String[] args) {
            SparkSession spark = 		 SparkSession.builder().master("local[2]").appName("DataSetEncoderExample").getOrCreate();
            List<Integer> data2 = Arrays.asList(30, 40, 50);
            //创建dataset
            Dataset<Integer> ds2 = spark.createDataset(data2,Encoders.INT());
            //filter算子
            Dataset<Integer> value = ds2.filter(ds2.col("value").gt(30));
            value.show();
        }
    }
    
    //结果
    +-----+
    |value|
    +-----+
    |   40|
    |   50|
    +-----+
    
  • groupBy算子

    /*
    *按照某列或某几列进行分组,然后汇总数据
    */
    public class TestSparkJava {
        public static void main(String[] args) {
            SparkSession spark = SparkSession.builder().master("local[2]").appName("DataSetEncoderExample").getOrCreate();
            List<String> data = Arrays.asList("chen_as", "li_as", "huang_as");
            //创建dataset
            Dataset<String> ds = spark.createDataset(data, Encoders.STRING());
            Dataset<Row> num = ds.withColumn("num", lit(12));
            //转换算子
            //4、groupby算子
            Dataset<Row> max = num.groupBy("value").max("num");
            max.show();
        }
    }
    //结果
    +--------+--------+
    |   value|max(num)|
    +--------+--------+
    | chen_as|      12|
    |huang_as|      12|
    |   li_as|      12|
    +--------+--------+
    
  • groupByKey算子

  • toDF算子

    //修改Dataset<Row>的列名
      Dataset<Row> result = sparksession.sql("select * from " + tableName + "Sheet1");
      Dataset<Row> rowDataset = result.toDF("userid", "name");
      rowDataset.show();
    
    //结果+------+----+
    |姓名  |年龄|
    +------+----+
    |    张三|18.0|
    |    李四|30.0|
    +------+----+
        
    +------+----+
    |userid|name|
    +------+----+
    |    张三|18.0|
    |    李四|30.0|
    +------+----+
    
2-3、动作算子
  • collect算子

    /*
    *将Dataset的全部数据变成一个列表
    */
    public class TestSparkJava {
        public static void main(String[] args) {
            SparkSession spark = SparkSession.builder().master("local[2]").appName("DataSetEncoderExample").getOrCreate();
            List<String> data = Arrays.asList("chen_as", "li_as", "huang_as");
            List<Integer> data2 = Arrays.asList(30, 40, 50);
            //创建dataset
            Dataset<String> ds = spark.createDataset(data, Encoders.STRING());
            Dataset<Integer> ds2 = spark.createDataset(data2,Encoders.INT());
            Dataset<Row> num = ds.withColumn("num", lit(12));
            Dataset<Row> num2 = num.withColumn("num2", lit(12));
            //动作算子
            //1、collect算子
            System.out.println(java.util.Arrays.toString((Object[]) num2.collect()));
    
        }
    }
    
    //结果如下
    [[chen_as,12,12], [li_as,12,12], [huang_as,12,12]]
    
  • take算子

    /*
    *获取前几个row,然后转成列表
    */
    public class TestSparkJava {
        public static void main(String[] args) {
            SparkSession spark = SparkSession.builder().master("local[2]").appName("DataSetEncoderExample").getOrCreate();
            List<String> data = Arrays.asList("chen_as", "li_as", "huang_as");
            List<Integer> data2 = Arrays.asList(30, 40, 50);
            //创建dataset
            Dataset<String> ds = spark.createDataset(data, Encoders.STRING());
            Dataset<Integer> ds2 = spark.createDataset(data2,Encoders.INT());
            Dataset<Row> num = ds.withColumn("num", lit(12));
            Dataset<Row> num2 = num.withColumn("num2", lit(12));
            //2、take算子
            System.out.println(Arrays.toString((Object[]) num2.take(2)));
    
        }
    }
    //结果如下
    [[chen_as,12,12], [li_as,12,12]
    
  • count算子

    /*
    *获取DataSet的获取行数
    */
    public class TestSparkJava {
        public static void main(String[] args) {
            SparkSession spark = SparkSession.builder().master("local[2]").appName("DataSetEncoderExample").getOrCreate();
            List<String> data = Arrays.asList("chen_as", "li_as", "huang_as");
            List<Integer> data2 = Arrays.asList(30, 40, 50);
            //创建dataset
            Dataset<String> ds = spark.createDataset(data, Encoders.STRING());
            Dataset<Integer> ds2 = spark.createDataset(data2,Encoders.INT());
            Dataset<Row> num = ds.withColumn("num", lit(12));
            Dataset<Row> num2 = num.withColumn("num2", lit(12));
            //3、count算子
            System.out.println(num2.count());
        }
    }
    
    //结果如下:
    3
    
  • foreach算子

    /*
    *foreach算子的作用是对Dataset的每一行进行操作
    */
    public class TestSparkJava {
        public static void main(String[] args) {
            SparkSession spark = SparkSession.builder().master("local[2]").appName("DataSetEncoderExample").getOrCreate();
            List<String> data = Arrays.asList("chen_as", "li_as", "huang_as");
            List<Integer> data2 = Arrays.asList(30, 40, 50);
            //创建dataset
            Dataset<String> ds = spark.createDataset(data, Encoders.STRING());
            Dataset<Integer> ds2 = spark.createDataset(data2,Encoders.INT());
            Dataset<Row> num = ds.withColumn("num", lit(12));
            Dataset<Row> num2 = num.withColumn("num2", lit(12));
            
            //4、foreach算子
            final Data data1 = new Data();
            num2.foreach(new ForeachFunction<Row>() {
                @Override
                public void call(Row row) throws Exception {
                     String value = row.getAs("value");
                     int num = row.getAs("num");
                    int num2 = row.getAs("num2");
                    data1.setValue(value);
                    data1.setNum(num);
                    data1.setNum2(num2);
                    System.out.println(data1.toString());
                }
            });
        }
    }
    //最后的输出结果
    Data{value='li_as', num=12, num2=12}
    Data{value='huang_as', num=12, num2=12}
    Data{value='chen_as', num=12, num2=12}
    
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值