Partitioner源碼
abstract class Partitioner extends Serializable {
def numPartitions: Int
def getPartition(key: Any): Int
}
源碼解釋:
一個對象,定義如何按鍵對鍵值對RDD中的元素進行分區。
將每個鍵映射到一個分區ID,從0到“numPartitions-1”。
注意,partitioner必須是確定性的,即它必須返回給定的相同分區id
相同的分區鍵。
簡單來說:
getPartition方法根據輸入的k-v對的key值返回一個Int型數據。可以理解爲這個Int數據就是分區的編號。
1.下面是Partitioner自定義分區器的例子
需求
根據日期的年份對數據分區,分區繼承Partitioner類並重寫三個方法,分區數設置爲4 ,2013、2014、2015、其它年份分別放在一個分區
對文件裏的取時間data和第二個字段組成新rdd,進行分區後進行保存
數據格式(分隔符爲 “,” )
數據文件下載地址
代碼演示
import org.apache.spark.rdd.RDD
import org.apache.spark.{Partitioner, SparkConf, SparkContext}
object test04 {
def main(args: Array[String]): Unit = {
//構建sc對象
val conf = new SparkConf().setMaster("local[*]").setAppName("test04")
val sc = new SparkContext(conf)
//讀取外部文件
val data: RDD[String] = sc.textFile("D:\\ChromeCoreDownloads\\000002.csv")
//分割每行數據,取出每行前兩個字段並做爲鍵值對
val tuple = data.map(line => {
val fields = line.split(",")
fields(0) -> fields(1)
})
//filter(! _._1.contains("date")) 過濾掉字段名
//partitionBy(new CustomPartitioner(4)) 使用自定義分區器,分區數爲 4
val result = tuple.filter(! _._1.contains("date")).partitionBy(new CustomPartitioner(4))
//將輸出文件保存到 out 文件夾
result.saveAsTextFile("out")
}
}
//自定義分區器
//需要重寫 Partitioner 的兩個方法
class CustomPartitioner(numPartition:Int) extends Partitioner {
override def numPartitions: Int = numPartition
override def getPartition(key: Any): Int = {
//key 這裏的類型爲Any
//需要將它轉換爲String類型,以便於後面的取值
val k = key.asInstanceOf[String]
//對date數據進行模式匹配
//k = 2013/10/21 k(3) = 3
k(3) match {
case '3' => 0 //將k(3)爲3的放在 0 號分區
case '4' => 1 //將k(3)爲4的放在 1 號分區
case '5' => 2 //將k(3)爲5的放在 2 號分區
case _ => 3 //將k(3)爲其他的放在 3 號分區
}
}
}
運行結果