1.sortByKey
無可非議sortByKey是Spark的最常用的排序,簡單的案例暫且跳過,下面給一個非簡單的案例,進入排序之旅
對下面簡單元祖,要求先按元素1升序,若元素1相同,則再按元素3升序
(1, 6, 3), (2, 3, 3), (1, 1, 2), (1, 3, 5), (2, 1, 2)
提示:sortByKey對於key是單個元素排序很簡單,如果key是元組如(X1,X2,X3.....),它會先按照X1排序,若X1相同,則在根據X2排序,依次類推...
由上面的分析,我們可以給出如下的代碼:
- val conf = new SparkConf()
- val sc = new SparkContext(conf)
- val array = Array((1, 6, 3), (2, 3, 3), (1, 1, 2), (1, 3, 5), (2, 1, 2))
- val rdd1 = sc.parallelize(array)
- //設置元素(e1,e3)爲key,value爲原來的整體
- val rdd2 = rdd1.map(f => ((f._1, f._3), f))
- //利用sortByKey排序的對key的特性
- val rdd3 = rdd2.sortByKey()
- val rdd4 = rdd3.values.collect
結果:
- rdd4: Array[(Int, Int, Int)] = Array((1,1,2), (1,6,3), (1,3,5), (2,1,2), (2,3,3))
2.sortBy
SortBy其實是SortBykey的加強版,比如上面的功能可以使用這個函數實現- val rdd2=rdd1.sortBy(f=>(f._1,f._3)).collect
- def sortBy[K](
- f: (T) => K,
- ascending: Boolean = true,
- numPartitions: Int = this.partitions.length)
- (implicit ord: Ordering[K], ctag: ClassTag[K]): RDD[T] = withScope {
- this.keyBy[K](f)
- .sortByKey(ascending, numPartitions)
- .values
- }
- def keyBy[K](f: T => K): RDD[(K, T)] = withScope {
- val cleanedF = sc.clean(f)
- map(x => (cleanedF(x), x))
- }
3.Ordering
Ordering在Spark的排序應用中隨處可見,比如上面的SortBy它就有一個隱式參數implicit ord: Ordering[K],如下摘抄自Scala提供AIP
對簡單的類型排序, quickSort 這裏使用了高階函數的柯里化,
爲第二個括號爲Ordering類型的隱式參數
- import scala.util.Sorting
- val pairs = Array(("a", 5, 2), ("c", 3, 1), ("b", 1, 3))
- // sort by 2nd element
- Sorting.quickSort(pairs)(Ordering.by[(String, Int, Int), Int](_._2))
- // sort by the 3rd element, then 1st
- Sorting.quickSort(pairs)(Ordering[(Int, String)].on(x => (x._3, x._1)))
- import scala.util.Sorting
- case class Person(name:String, age:Int)
- val people = Array(Person("bob", 30), Person("ann", 32), Person("carl", 19))
- // sort by age
- object AgeOrdering extends Ordering[Person] {
- def compare(a:Person, b:Person) = a.age compare b.age
- }
- Sorting.quickSort(people)(AgeOrdering)
因爲sortByKey實現了Ordering的很多功能,下面以Spark中的top函數爲例
- def top(num: Int)(implicit ord: Ordering[T]): Array[T] = withScope {
- takeOrdered(num)(ord.reverse)
- }
- val array = Array((1, 3, 3), (2, 6, 3), (1, 1, 2), (1, 5, 4), (2, 1, 2))
- val rdd1 = sc.parallelize(array)
- val result=rdd1.top(3)(Ordering.by[(Int, Int, Int), Int](_._2))
結果:
- result: Array[(Int, Int, Int)] = Array((2,6,3), (1,5,4), (1,3,3))