spark官方常用的32个算子
spark常用的Transformation
import org.apache.spark.{HashPartitioner, SparkConf, SparkContext}
import scala.collection.mutable.ListBuffer
object Transformation {
val conf = new SparkConf().setAppName("Transformation").setMaster("local")
val sc = new SparkContext(conf)
def main(args: Array[String]): Unit = {
// map()
// filter()
// flatMap()
// mapPartitions()
// mapPartitionsWithIndex()
// sample()
// union()
// intersection()
// distinct()
// groupByKey()
// reduceByKey()
// aggregateByKey()
// sortByKey()
// join()
// cogroup()
// cartesian()
// coalesce()
// repartition()
repartitionAndSortWithinPartitions()
}
def map()={
sc.parallelize(1 to 10, 3)
.map((_ + 1))
.foreach(println)
}
/**
* filter(function)
* 过滤操作,满足filter内function函数为true的RDD内所有元素组成一个新的数据集
*/
def filter(): Unit ={
sc.parallelize(1 to 10, 1)
.filter(it => it % 2 == 0)
.foreach(println)
}
/**
* flatMap(function)
* map是对RDD中元素逐一进行函数操作映射为另外一个RDD,而flatMap操作是将函数应用于RDD之中
* 的每一个元素,将返回的迭代器的所有内容构成新的RDD。而flatMap操作是将函数应用于RDD中每一
* 个元素,将返回的迭代器的所有内容构成RDD。
*
* flatMap与map区别在于map为“映射”,而flatMap“先映射,后扁平化”,map对每一次(func)都产生
* 一个元素,返回一个对象,而flatMap多一步就是将所有对象合并为一个对象。
*/
def flatMap(): Unit ={
sc.parallelize(1 to 5, 1)
.flatMap(( _ to 5))
.foreach(println)
}
/**
* mapPartitions(function)
* 区于foreachPartition(属于Action,且无返回值),而mapPartitions可获取返回值。
* 与map的区别前面已经提到过了,但由于单独运行于RDD的每个分区上(block),
* 所以在一个类型为T的RDD上运行时,(function)必须是
* Iterator<T> => Iterator<U>类型的方法(入参)。
*/
def mapPartitions(): Unit ={
sc.parallelize(1 to 10, 3)
.mapPartitions(it => {for(e <- it) yield e * 2})
.foreach(println)
}
/**
* mapPartitionsWithIndex(function)
* 与mapPartitions类似,但需要提供一个表示分区索引值的整型值作为参数,因此function必
* 须是(int, Iterator<T>)=>Iterator<U>类型的。
*/
def mapPartitionsWithIndex(): Unit ={
sc.parallelize(1 to 10, 3)
.mapPartitionsWithIndex((x, it) =>{
val res = List[String]()
var i =0
while (it.hasNext){
i += it.next()
}
res.::(x + ":" + i).iterator
})
.foreach(println)
}
/**
* sample(withReplacement, fraction, seed)
* withReplacement是否放回,fraction采样比例,seed用于指定的随机数生成器的种子
* 是否放回抽样分true和false,fraction取样比例为(0, 1]。seed种子为整型实数。
*/
def sample(): Unit ={
sc.parallelize(1 to 10, 3)
.sample(false, 0.5, 1)
.foreach(println)
}
/**
* union(otherDataSet)
* 对于源数据集和其他数据集求并集,不去重
*/
def union(): Unit ={
val data = sc.parallelize(1 to 10, 3)
sc.parallelize(1 to 10, 3)
.union(data)
.foreach(println)
}
/**
* intersection(otherDataSet)
* 对于源数据集和其他数据集求交集,并去重,且无序返回。
*/
def intersection(): Unit ={
val data = sc.parallelize(6 to 12, 1)
sc.parallelize(1 to 10, 1)
.intersection(data)
.foreach(println)
}
/**
* distinct([numTasks])
* 返回一个在源数据集去重之后的新数据集,即去重,并局部无序而整体有序返回。
*/
def distinct(): Unit ={
sc.parallelize(List(1,3,5,7,12,34,1,67,12,3,5,12,12,12,7,7,7,7), 2)
.distinct()
.collect()
.foreach(println)
}
/**
* groupByKey([numTasks])
* groupByKey是将PairRDD中拥有相同key值得元素归为一组
*/
def groupByKey(): Unit ={
sc.parallelize(List(("武当", "张三丰"), ("峨眉", "灭绝师太"), ("武当", "张无忌"), ("峨眉", "周芷若")))
.groupByKey()
.foreach(println)
}
/**
* reduceByKey(function,[numTasks])
* reduceByKey仅将RDD中所有K,V对中K值相同的V进行合并。
*/
def reduceByKey(): Unit ={
sc.parallelize(List(("武当", 99), ("少林", 97), ("武当", 89), ("少林", 77)))
.reduceByKey(_+_)
.foreach(println)
}
/**
* aggregateByKey(zeroValue)(seqOp, combOp, [numTasks])
* aggregateByKey函数对PairRDD中相同Key的值进行聚合操作,在聚合过程中同样使用了一个中立的初始值。
* 和aggregate函数类似,aggregateByKey返回值的类型不需要和RDD中value的类型一致。因为aggregateByKey
* 是对相同Key中的值进行聚合操作,所以aggregateByKey函数最终返回的类型还是Pair RDD,对应的结果是Key和
* 聚合好的值;而aggregate函数直接是返回非RDD的结果,这点需要注意。在实现过程中,定义了三个aggregateByKey
* 函数原型,但最终调用的aggregateByKey函数都一致。
* 或者
* 类似reduceByKey,对pairRDD中想用的key值进行聚合操作,使用初始值(seqOp中使用,而combOpenCL中未使用)
* 对应返回值为pairRDD,而区于aggregate(返回值为非RDD)
*/
def aggregateByKey(): Unit ={
sc.parallelize(List("hello world!", "I am a dog", "hello world!", "I am a dog"))
.flatMap(_.split(" "))
.map(( _, 1))
.aggregateByKey(0)(_+_,_+_)
.foreach(tuple =>println(tuple._1+"->"+tuple._2))
}
/**
* sortByKey([ascending], [numTasks])
*
*/
def sortByKey(): Unit ={
sc.parallelize(List((99, "张三丰"), (96, "东方不败"), (66, "林平之"), (98, "聂风")))
.sortByKey(false)
.foreach(tuple => println(tuple._2 + "->" + tuple._1))
}
/**
* join(otherDataSet,[numTasks])
* 加入一个RDD,在一个(k,v)和(k,w)类型的dataSet上调用,返回一个(k,(v,w))的pair dataSet。
*/
def join(): Unit ={
val list1RDD = sc.parallelize(List((1, "东方不败"), (2, "令狐冲"), (3, "林平之")))
val list2RDD = sc.parallelize(List((1, 99), (2, 98), (3, 97)))
list1RDD.join(list2RDD)
.foreach(println)
}
/**
* cogroup(otherDataSet,[numTasks])
* 对两个RDD中的KV元素,每个RDD中相同key中的元素分别聚合成一个集合。与reduceByKey不同的是针对
* 两个RDD中相同的key的元素进行合并。
* 或者
* 合并两个RDD,生成一个新的RDD。实例中包含两个Iterable值,第一个表示RDD1中相同值,第二个表示RDD2
* 中相同值(key值),这个操作需要通过partitioner进行重新分区,因此需要执行一次shuffle操作。(
* 若两个RDD在此之前进行过shuffle,则不需要)
*/
def cogroup(): Unit ={
val list1RDD = sc.parallelize(List((1, "www"), (2, "bbs")))
val list2RDD = sc.parallelize(List((1, "cnblog"), (2, "cnblog"), (3, "very")))
val list3RDD = sc.parallelize(List((1, "com"), (2, "com"), (3, "good")))
list1RDD.cogroup(list2RDD,list3RDD)
.foreach(println)
}
/**
* cartesian(otherDataSet)
* 求笛卡尔乘积。该操作不会执行shuffle操作。
*
*/
def cartesian(): Unit ={
val list1RDD = sc.parallelize(List("A","B"))
val list2RDD = sc.parallelize(List(1,2,3))
list1RDD.cartesian(list2RDD)
.foreach(println)
}
def pipe(): Unit ={
}
/**
* coalesce(numPartitions)
* 重新分区,减少RDD中分区的数量到numPartitions。
*
*/
def coalesce(): Unit ={
sc.parallelize(List(1,2,3,4,5,6,7,8,9),3)
.coalesce(1)
.foreach(println)
}
/**
* repartition(numPartitions)
* repartition是coalesce接口中shuffle为true的简易实现,即Reshuffle RDD并随机分区,使各分区数据量
* 尽可能平衡。若分区之后分区数远大于原分区数,则需要shuffle。
*/
def repartition(): Unit ={
sc.parallelize(List(1,2,3,4),1)
.repartition(2)
.foreach(println)
}
/**
*.repartitionAndSortWithinPartitions(partitioner)
* repartitionAndSortWithinPartitions函数是repartition函数的变种,与repartition函数不同的是,
* repartitionAndSortWithinPartitions在给定的partitioner内部进行排序,性能比repartition要高。
*/
def repartitionAndSortWithinPartitions(){
val listRDD = sc.parallelize(List(1, 4, 55, 66, 33, 48, 23),1)
listRDD.map(num => (num,num))
.repartitionAndSortWithinPartitions(new HashPartitioner(2))
.mapPartitionsWithIndex((index,iterator) => {
val listBuffer: ListBuffer[String] = new ListBuffer
while (iterator.hasNext) {
listBuffer.append(index + "_" + iterator.next())
}
listBuffer.iterator
},false)
.foreach(println)
}
}
spark常用的Action
import org.apache.spark.{SparkConf, SparkContext}
object Action {
val conf = new SparkConf().setAppName("Action").setMaster("local")
val sc = new SparkContext(conf)
def main(args: Array[String]): Unit = {
// reduce()
// collect()
// count()
// first()
// takeSample()
// take()
// takeOrdered()
// saveAsTextFile()
// saveAsSequenceFile()
countByKey()
}
/**
* reduce(function)
* reduce其实是将RDD中的所有元素进行合并,当运行call方法时,会传入两个参数,
* 在call方法中将两个参数合并后返回,而这个返回值回合一个新的RDD中的元素再次传入call方法中,
* 继续合并,直到合并到只剩下一个元素时。
*/
def reduce(): Unit ={
val result = sc.parallelize(List(1,2,3,4,5,6))
.reduce((x,y) => x+y)
println(result)
}
/**
* count()
* 将一个RDD以一个Array数组形式返回其中的所有元素。
*/
def collect(): Unit ={
val array = sc.parallelize(1 to 10, 2)
.collect()
array.foreach(println)
}
/**
* count()
* 返回数据集中元素个数,默认Long类型。
*/
def count(): Unit ={
println(sc.parallelize(1 to 10, 2).count())
}
/**
* first()
* 返回数据集的第一个元素(类似于take(1))
*/
def first(): Unit ={
println(sc.parallelize(1 to 10, 2).first())
}
/**
* takeSample(withReplacement, num, [seed])
* 对于一个数据集进行随机抽样,返回一个包含num个随机抽样元素的数组,withReplacement表示
* 是否有放回抽样,参数seed指定生成随机数的种子。
* 该方法仅在预期结果数组很小的情况下使用,因为所有数据都被加载到driver端的内存中。
*/
def takeSample(): Unit ={
val array = sc.parallelize(1 to 10, 2).takeSample(true,3,1)
array.foreach(println)
}
/**
* take(n)
* 返回一个包含数据集前n个元素的数组(从0下标到n-1下标的元素),不排序。
*/
def take(): Unit ={
val array = sc.parallelize(List(2,7,1,8,3),2).take(3)
array.foreach(println)
}
/**
* takeOrdered(n,[ordering])
* 返回RDD中前n个元素,并按默认顺序排序(升序)或者按自定义比较器顺序排序。
*/
def takeOrdered(): Unit ={
val array = sc.parallelize(List(2,7,1,8,3),2).takeOrdered(3)
array.foreach(println)
}
/**
* saveAsTextFile(path)
* 将dataSet中元素以文本文件的形式写入本地文件系统或者HDFS等。Spark将对每个元素调用toString方法,
* 将数据元素转换为文本文件中的一行记录。
* 若将文件保存到本地文件系统,那么只会保存在executor所在机器的本地目录。
*/
def saveAsTextFile(): Unit ={
sc.parallelize(List(2,7,1,8,3),2).saveAsTextFile("E:\\data\\")
}
/**
* saveAsSequenceFile(path)(Java and Scala)
* 将dataSet中元素以Hadoop SequenceFile的形式写入本地文件系统或者HDFS等。(对pairRDD操作)
*/
def saveAsSequenceFile(): Unit ={
sc.parallelize(List(2,7,1,8,3),2).saveAsObjectFile("E:\\data\\")
}
/**
* countByKey()
* 用于统计RDD[K,V]中每个K的数量,返回具有每个key的计数的(k,int)pairs的hashMap。
*/
def countByKey(): Unit ={
val map = Map("qq" -> "11", "ww" -> "22", "ee" -> "33", "rr" -> "44", "5" -> "55", "6" -> "66")
sc.parallelize(map.toList, 2)
.countByKey()
.foreach(println)
}
/**
* foreach(function)
*/
def foreach(): Unit ={
}
}