Spark RDD操作函数说明

来源:互联网 发布:香港底层 知乎 编辑:程序博客网 时间:2024/06/06 09:54

RDD分两类:actions 与 transformation。transformation中有些算子理解起来比较费解,先理解action算子再理解transformation算子会容易些。


ACTION

collect

count

first

返回RDD的第一个成员,等价于take(1)

take

返回RDD前n个成员

takeSample

语法:

 def takeSample( withReplacement: Boolean, num: Int, seed: Long = Utils.random.nextLong): Array[T]

说明: 和 sample 用法相同,只不第二个参数换成了个数。返回也不是RDD,而是collect

takeOrdered

语法:

def takeOrdered(num: Int): JList[T]def takeOrdered(num: Int, comp: Comparator[T]): JList[T]

说明: 用于从RDD中,按照默认(升序)或指定排序规则,返回前num个元素。

saveAsTextFile

saveAsSequenceFile

以SequenceFile格式保存,成员类型必须实现Writeable接口或可以被隐式转换为Writable类型

saveAsObjectFile

将RDD中的元素序列化成对象,存储到文件中

countByKey

仅适用于(K, V)类型,对key计数,返回(K, Int)

foreach

类似map,但无返回值,常用于更新计数器或输出数据至外部存储系统。

reduce

语法:

def reduce(f: (T, T) => T): T

说明: Rdd<T> resRdd = rdd<T>.reduce(func: (T,T) => T)
对rdd内所有元素进行合并计算,方法是从左至右两两计算,最后只得到一个值

aggregate

语法:

def aggregate[U: ClassTag](zeroValue: U)(seqOp: (U, T) => U, combOp: (U, U) => U): U

说明: 即每个分区内以 zeroValue 初始值进行 reduce ,再对 各分区结果 以及 zeroValue 进行 reduce 。 与 reduce 的区别是, aggregate 有对分区内的操作定义 和 对分区间的操作定义;还有初始值定义 ;reduce 仅有一个统一的对所有元素的操作定义

Rdd<U> resRdd = rdd<T>.aggregate(zeroValue: U)( seqOp: (U, T) => U, combOp: (U, U) => U )   

举例:

rdd 有两个分区 第一个分区中包含5,4,3,2,1  第二个分区中包含10,9,8,7,6scala> rdd.aggregate(1)(     |           {(x : Int,y : Int) => x + y},      |           {(a : Int,b : Int) => a + b}     |     )res17: Int = 58分析: zeroValue 为 1 (即第一个括号内值)先在每个分区中迭代执行 (x : Int,y : Int) => x + y 并且使用zeroValue的值1即:part_0中 zeroValue+5+4+3+2+1 = 1+5+4+3+2+1 = 16part_1中 zeroValue+10+9+8+7+6 = 1+10+9+8+7+6 = 41再将两个分区的结果合并(a : Int,b : Int) => a + b ,并且使用zeroValue的值1即:zeroValue+part_0+part_1 = 1 + 16 + 41 = 58


Transformation

mapPartitions

语法:

def mapPartitions[U: ClassTag]( f: Iterator[T] => Iterator[U], preservesPartitioning: Boolean = false): RDD[U]

说明: 参数 preservesPartitioning 表示是否保留父RDD的partitioner分区信息。 如果在映射的过程中需要频繁创建额外的对象,使用 mapPartitions 要比map高效。
示例:

Rdd<Iterator<T>> resRdd = rdd<T>.mapPartitions(func: Iterator[T] => Iterator[U], preservesPartitioning: Boolean = false)    // 输入为一个分区的所有数据,输出 Iterator

mapPartitionsWithIndex

语法:

def mapPartitionsWithIndex[U](f: (Int, Iterator[T]) => Iterator[U], preservesPartitioning: Boolean = false)(implicit arg0: ClassTag[U]): RDD[U]

说明: 同mapPartitions,不过提供了两个参数,第一个参数为分区的索引。
示例: Rdd<Iterator<T>> resRdd = rdd<T>.mapPartitions(func: (Int, Iterator[T]) => Iterator[U], preservesPartitioning: Boolean = false)

sample

语法:

def sample( withReplacement: Boolean, fraction: Double, seed: Long = Utils.random.nextLong): RDD[T]

说明: withReplacement 为true时表示抽样之后还放回,可以被多次抽样,false表示不放回; fraction 表示抽样比例;
Rdd resRdd = rdd.sample(false,0.8)

union

语法: def union(other: RDD[T]): RDD[T]
说明: 简单合并两个RDD,不去重,要求两个RDD中的元素类型一致

Rdd<T> resRdd = rdd<T>.union(rdd2<T>)

举例:

data1RDD = sc.parallelize(Arrays.asList("张三", "李四"));data2RDD = sc.parallelize(Arrays.asList("tom", "gim"));data1RDD.union(data2RDD) 结果为元素分别为"张三", "李四""tom", "gim"的rdd

intersection

语法: def intersection(other: RDD[T]): RDD[T]
说明: 返回两个RDD的交集

groupby

语法:

def groupBy[K](f: T => K)(implicit kt: ClassTag[K]): RDD[(K, Iterable[T])]   // K 即组号

说明: 将元素分组, call 返回值为组号

Rdd<K, Iterable[T]> resRdd = rdd<T>.groupBy(func: T => K)

groupByKey

语法: def groupByKey(): RDD[(K, Iterable[V])]
说明: rdd

Rdd<K, Iterable[V]> resRdd = rdd<K,V>.groupByKey()

reduceByKey

语法: def reduceByKey(func: (V, V) => V): RDD[(K, V)]
说明:

Rdd<K, V> resRdd = rdd<K, V>.reduceByKey(func: (V, V) => V)   //从左向右合并

aggregateByKey

语法: def aggregateByKey[U: ClassTag](zeroValue: U)(seqOp: (U, V) => U, combOp: (U, U) => U): RDD[(K, U)]
说明: 对 key 相同的值进行合并,合并方法是 先各分区内合并,再分区间合并。合并都有 zeroValue 参与
zeroValue :表示在每个分区中第一次拿到key值时,用于创建一个返回类型的函数,这个函数最终会被包装成先生成一个返回类型,然后通过调用seqOp函数,把第一个key对应的value添加到这个类型U的变量中。
seqOp :这个用于把迭代分区中key对应的值添加到zeroValue创建的U类型实例中。
combOp :这个用于合并每个分区中聚合过来的两个U类型的值。
举例:

rdd 有两个分区 ,rdd类型为 <Int, Int>分区一数据(1,3) (1,2)分区二数据(1,4) (2,3)代码:    def seq(a: String, b: Int): String = {   // a 为分区输出类型,b 为分区内元素类型        println("seq: " + a + "\t " + b)        a + b    }    def comb(a: String, b: String): String = {  // a 与 b 都是分区输出类型        println("comb: " + a + "\t " + b)        a + b    }    val aggregateByKeyRDD: RDD[(Int, String)] = rdd.aggregateByKey("100")(seq, comb)**说明**//分区一相同key的数据进行合并。下面形式 seq: 输入参数seq: 100     3   //(1,3)开始和中立值进行合并  合并结果为 1003seq: 1003     2   //因为key都是1,前次合并结果与(1,2)再次合并 结果为 10032  //分区二相同key的数据进行合并seq: 100     4  //(1,4) 开始和中立值进行合并 1004seq: 100     3  //(2,3) 开始和中立值进行合并 1003将两个分区的结果进行合并//key为2的,只在一个分区存在,不需要合并 (2,1003)(2,1003)//key为1的, 在两个分区存在,并且数据类型一致,合并comb: 10032     1004(1,100321004)最终结果是 :(1,100321004),(2,1003)

sortBy

语法: def sortBy[K]( f: (T) => K, ascending: Boolean = true, numPartitions: Int = this.partitions.length): RDD[T]
说明: 按f函数输出结果排序, ascending true为升序, rdd分区数改为 numPartitions

sortByKey

语法: def sortByKey(ascending: Boolean = true, numPartitions: Int = self.partitions.length): RDD[(K, V)]
说明: 按key值排序, (3, 3) (2, 2) (1, 4) (2, 3) 输出: (3,3) (2,2) (2,3) (1,4)

join

语法: def join[W](other: RDD[(K, W)]): RDD[(K, (V, W))]
说明: join相当于SQL中的内关联join,只返回两个RDD根据K可以关联上的结果
Rdd<(K, (V, W))> resRdd = rdd<K, V>.join(rdd2<K, W>)
举例:

sc.parallelize(List((1, "苹果"), (2, "梨"), (3, "香蕉"), (4, "石榴")))        .join(sc.parallelize(List((1, 7), (2, 3), (4, 3), (5, 9))))        .foreach(println)结果: (4,(石榴,3))(1,(苹果,7))(2,(梨,3))

cogroup

语法:

def cogroup[W1, W2, W3](other1: RDD[(K, W1)],                        other2: RDD[(K, W2)],                     other3: RDD[(K, W3)],                     partitioner: Partitioner)        : RDD[(K, (Iterable[V], Iterable[W1], Iterable[W2], Iterable[W3]))]  // 此为与三个其它rdd cogroup的,还有参数为一个rdd、两个rdd的 cogroup 函数

说明: cogroup相当于SQL中的全外关联full outer join,返回左右RDD中的记录,关联不上的为空。
与 join 的区别是:1 join只能一次关联一个rdd;2 join是内关联(不返回关联不上的),cogroup 是外关联(关联不上返回空)
举例:

var rdd1 = sc.makeRDD(Array(("A","1"),("B","2"),("C","3")),2)var rdd2 = sc.makeRDD(Array(("A","a"),("C","c"),("D","d")),2)var rdd3 = rdd1.cogroup(rdd2)rdd3.collect结果: Array[(String, (Iterable[String], Iterable[String]))] = Array(    (B,(CompactBuffer(2),CompactBuffer())),     (D,(CompactBuffer(),CompactBuffer(d))),     (A,(CompactBuffer(1),CompactBuffer(a))),     (C,(CompactBuffer(3),CompactBuffer(c))))

cartesian

语法: def cartesian[U: ClassTag](other: RDD[U]): RDD[(T, U)]
说明: 两个RDD进行笛卡尔积合并
Rdd<(T, U)> resRdd = rdd<T>.cartesian(rdd2<U>)
举例:

var rdd1 = sc.makeRDD(Array("张三", "李四", "王五"))var rdd2 = sc.makeRDD(Array(60, 70, 80))namesRDD.cartesian(scoreRDD).foreach(println)结果:张三  60张三  70张三  80李四  60李四  70李四  80王五  60王五  70王五  80

pipe

语法:

def pipe(command: String): RDD[String]def pipe(command: String, env: Map[String, String]): RDD[String]

说明: 执行cmd命令,创建RDD
举例:

val data = List("hi", "hello", "how", "are", "you")    sc.makeRDD(data)        .pipe("/Users/zhangws/echo.sh")        .collect()        .foreach(println)echo.sh 内容为:(    #!/bin/bash    echo "Running shell script"    RESULT=""    while read LINE; do      RESULT=${RESULT}" "${LINE}    done    echo ${RESULT} > /Users/zhangws/out123.txt)结果:out123.txthi hello how are you输出Running shell script

coalesce

语法: def coalesce(numPartitions: Int, shuffle: Boolean = false)(implicit ord: Ordering[T] = null): RDD[T]
说明: 用于将RDD进行重分区,使用HashPartitioner。且该RDD的分区个数等于numPartitions个数。如果shuffle设置为true,则会进行shuffle。

repartition

repartitionAndSortWithinPartitions

语法: def repartitionAndSortWithinPartitions(partitioner: Partitioner): RDD[(K, V)]
说明: 根据给定的Partitioner重新分区,并且每个分区内根据comp实现排序。

0 0
原创粉丝点击