【Spark学习】Partitioner分区器初体验

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 号分区
    }
  }
}

运行结果
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章