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}