1. 定义
/*
* 1. 定义
* def partitionBy(partitioner: Partitioner): RDD[(K, V)]
*
* 2. 功能
* 将数据类型为key-value的Rdd 按照指定 Partitioner 重新进行分区
* 默认分区器为 HashPartitioner
*
* 3. note
* 1. 参数必须是 org.apache.spark.Partitioner的实现类
* 2. partitionBy算子 只能操作元素类型为 (key,value)的Rdd
* 3. 只能按照key来分区
*
* 4. 思考
* 1. 如果重分区的分区器和当前 RDD 的分区器一样怎么办?
* if (self.partitioner == Some(partitioner)) self
* partitionBy 会判断 传入分区器和 rdd分区器是否类型相同
* 如果类型相同,则返回 Rdd的引用
*
* 2. Spark 还有其他分区器吗?
* HashPartitioner、RangePartitioner
* */
2. 示例
package keyvaluePak {
import org.apache.spark.rdd.RDD
import org.apache.spark.{HashPartitioner, Partitioner, SparkConf, SparkContext}
//自定义分区器
//必须是 org.apache.spark.Partitioner的实现类
//需求 : 按 正负数分区
class custPartitioner(partitions: Int) extends Partitioner {
override def numPartitions: Int = partitions
//通过对key判断,返回对应的分区编号 part-0000X
override def getPartition(key: Any): Int = {
if (key.asInstanceOf[Int] >= 0) {
0
} else {
1
}
}
}
object partitionByTest extends App {
val sparkconf: SparkConf = new SparkConf().setMaster("local").setAppName("distinctTest")
val sc: SparkContext = new SparkContext(sparkconf)
val rdd: RDD[(Int, String)] = sc.makeRDD(List((1, "x"), (-2, "x"), (3, "x"), (-4, "x"), (5, "x"), (-6, "x"), (7, "x")), 2)
//使用自定义分区器
val rdd2: RDD[(Int, String)] = rdd.partitionBy(new custPartitioner(2))
//使用 HashPartitioner 分区器
val rdd3: RDD[(Int, String)] = rdd.partitionBy(new HashPartitioner(2))
private val rdd4: RDD[(Int, String)] = rdd3.partitionBy(new HashPartitioner(2))
//使用匿名内部类
// 按照 奇偶性分区
private val rdd5: RDD[(Int, String)] = rdd.partitionBy(
new Partitioner {
override def numPartitions: Int = 3 //指定分区个数
override def getPartition(key: Any): Int = {
if (key.asInstanceOf[Int].abs % 2 == 0) {
0
} else {
1
}
}
}
)
//rdd2.saveAsTextFile("Spark_319/src/output/01")
//rdd3.saveAsTextFile("Spark_319/src/output/02")
rdd5.saveAsTextFile("Spark_319/src/output/05")
sc.stop()
}
}