每天都在努力的我,每天都在努力的你,总有一天我们会相见

   Spark collect和collectAsList是用于将RDD/DataFrame/DataSet的所有元素检索到驱动程序节点的操作。如果数据集较大,使用collect之后可能会导致内存不足

val data = Seq(Row(Row("James","","Smith"),"36636","M",3000), 

Row(Row("Michael","Rose",""),"40288","M",4000), 

Row(Row("Robert","","Williams"),"42114","M",4000),

 Row(Row("Maria","Anne","Jones"),"39192","F",4000), 

Row(Row("Jen","Mary","Brown"),"","F",-1)) 
val schema = new StructType()
.add("name",new StructType()
.add("firstname",StringType) 
.add("middlename",StringType) 
.add("lastname",StringType)) 
.add("id",StringType) 
.add("gender",StringType) 
.add("salary",IntegerType) 
val dataFrame = sparkSession.createDataFrame(
sparkSession.sparkContext.parallelize(data), schema)

        在一般的情况下,使用show()默认的情况下显示的前20行。

使用Collect()和CollectAsList()

        collect()动作函数用于数据集中检索所有元素,作为Array[Row]的一部分。

        什么意思呢?

        collect返回的是数组类型的,不过这个数组里面包含的Row对象。拿上面的数据作为例子.

 一个Array[Row] =》("Michael","Rose","")

        collectAsList()函数类似于collect,但是返回的是Java的列表

        collect() : scala.Array[T] collectAsList() : java.util.List[T]

val colList = df.collectAsList() 
val colData = df.collect() 
colData.foreach(row=> { 
val salary = row.getInt(3)
//Index starts from zero
 println(salary) })

        上面代码就是将dataFrame经过Collect之后的返回的Array[Row]进行遍历。

        问题来了,上面的数据,第一个字段name是嵌套字段,如何打印嵌套字段里面的数据。

val collist = dataFrame.collectAsList() 
val colData = dataFrame.collect() 
colData.foreach(row => {
 // 总共四个字段 name,id,gender,salary 
val salary = row.getInt(3) 
val fullName = row.getStruct(0) 
val firstname = fullName.getString(0) 
val senondname = fullName.get(1) 
val lastName = fullName.getAs[String]("lastname") 
println(salary + " " +firstname + " " + senondname + " " + lastName) })

        对于嵌套字段,使用getStruct首先获取到嵌套字段,获取之后使用get来获取里面的嵌套字段,下表从0开始。

spark collect spark collectaslist_spark collect


何时避免使用Collect()

        collect通常用于处理小数据集,当collect大数据集之后,可能会导致内存不足,避免使用大数据集在collect上

如何删除重复行

        在Spark SQL中可以使用distinct进行去重,删除重复的行或者列。

        distinct可以删除所有列上具有相同值的行,dropDpulicates可以删除多个选定列上具有相同值的行列。

        先看一下数据集

val simpleData = Seq(("James","Sales",3000), 
("michael","Sales",4600),
 ("Robert","Sales",4100), 
("Maria","Finance",3000), 
("James", "Sales", 3000), 
("Scott", "Finance", 3300),
 ("Jen", "Finance", 3900),
 ("Jeff", "Marketing", 3000), 
("Kumar", "Marketing", 2000), 
("Saif", "Sales", 4100)) 
val dataFrame = simpleData.toDF("employees_name", "department", "salary") 

dataFrame.show()

        可以看到James这个id中有两次出现,所有的值一摸一样,其它的数据有四行在deparment和salary中具有重复值。

        如果只是用distinct的话,那么去重的只有James。

        val value = dataFrame.distinct() println(value.count())

        本来有10条数据,经过distinct之后有9条数据,因为去重了一条数据

        如果想要去除某个列相同的数据的行,那么使用dropDuplicate就可以删除DataFrame上重复的行。

        如果使用dropDuplicate函数的时候没有指定参,那么作用就是和distinct的作用是一样的。

下面通过添加参数来实现通过重复列进行删除。

        val value2 = dataFrame.dropDuplicates("department", "salary") println(value2.count())

        上面的数据中有四条数据是department和salary都是一样的。

        所以后面经过dropDuplicates之后的数据变成了8行。

总结

        人不可能一天都在学习,但是我们可以保持每天都在学习。

        我的她也要越来越好呢