Spark算子[13]:sortByKey、sortBy、二次排序 源码实例详解

Spark Java API】Action(4)—sortBy、takeOrdered、takeSample spark java api... 阅读详情

sortBy是对标准的RDD进行排序。[在scala语言中,RDD与PairRDD没有太严格的界限]。
sortByKey函数是对PairRDD进行排序,也就是有Key和Value的RDD。


sortBy

源码

  /**
   * RDD.scala
   * Return this RDD sorted by the given key function.
   */
  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
  }

该函数最多可以传三个参数:
第一个参数是一个函数,该函数的也有一个带T泛型的参数,返回类型和RDD中元素的类型是一致的;
第二个参数是ascending,从字面的意思大家应该可以猜到,是的,这参数决定排序后RDD中的元素是升序还是降序,默认是true,也就是升序;
第三个参数是numPartitions,该参数决定排序后的RDD的分区个数,默认排序后的分区个数和排序之前的个数相等,即为this.partitions.size。

从sortBy函数的实现可以看出,第一个参数是必须传入的,而后面的两个参数可以不传入。而且sortBy函数函数的实现依赖于sortByKey函数,关于sortByKey函数后面会进行说明。keyBy函数也是RDD类中进行实现的,它的主要作用就是将将传进来的每个元素作用于f(x)中,并返回tuples类型的元素,也就变成了Key-Value类型的RDD了,它的实现如下:

def keyBy[K](f: T => K): RDD[(K, T)] = withScope {
  val cleanedF = sc.clean(f)
  map(x => (cleanedF(x), x))
}

Scala版本案例1

针对scala语言的pairRDD操作

def sortBy(): Unit = {
  val conf = new SparkConf().setMaster("local").setAppName("sortBy")
  val sc = new SparkContext(conf)
  val rdd = sc.makeRDD(List(("a",0),("d",5),("d",2),("c",1),("b",2),("b",0)),4)

  // 按照tuple2的第二个元素降序排列
  val res =rdd.sortBy(_._2,false,2)
  res.foreach(x=> print(x+ " "))
}

结果:(d,5) (d,2) (b,2) (c,1) (a,0) (b,0)


Scala版本案例2

针对scala的rdd操作

def sortBy(): Unit = {
  val conf = new SparkConf().setMaster("local").setAppName("sortBy")
  val sc = new SparkContext(conf)
  val rdd = sc.makeRDD(List(5,1,9,12),2)

  val res =rdd.sortBy(x=>x,false,1) //其中的x=>x相当于是函数,不能用_代替
  res.foreach(x=> print(x+ " "))
}

结果:12 9 5 1

上面的实例对rdd中的元素进行降序排序。并对排序后的RDD的分区个数进行了修改,上面的res就是排序后的RDD,默认的分区个数是2,而我们对它进行了修改,所以最后变成了1。


Java版本案例

org.apache.spark.api.java.JavaRDD源码如下:

/**
 * Return this RDD sorted by the given key function.
 */
def sortBy[S](f: JFunction[T, S], ascending: Boolean, numPartitions: Int): JavaRDD[T] = {
  def fn: (T) => S = (x: T) => f.call(x)
  import com.google.common.collect.Ordering  // shadows scala.math.Ordering
  implicit val ordering = Ordering.natural().asInstanceOf[Ordering[S]]
  implicit val ctag: ClassTag[S] = fakeClassTag
  wrapRDD(rdd.sortBy(fn, ascending, numPartitions))
}

需要注意的是,此处和scala不同,必须是三个参数!

private static void sortBy() {
    SparkConf conf = new SparkConf().setAppName("sortBy").setMaster("local");
    JavaSparkContext sc = new JavaSparkContext(conf);

    List<Integer> numList = Arrays.asList(1, 5, 3, 5, 6, 7, 0, 1, 10);
    JavaRDD<Integer> numRdd = sc.parallelize(numList);

    Function<Integer, Integer> fun1 = new Function<Integer, Integer>() {
        @Override
        public Integer call(Integer v1) throws Exception {
            return v1;
        }
    };

    JavaRDD<Integer> res = numRdd.sortBy(fun1, false, 1);
    res.foreach(x -> System.out.println(x));

    sc.close();
}

结果:10 7 6 5 5 3 1 1 0


sortByKey

sortByKey函数作用于Key-Value形式的RDD,并对Key进行排序。
它是在org.apache.spark.rdd.OrderedRDDFunctions中实现的。
 
源码

def sortByKey(ascending: Boolean = true, numPartitions: Int = self.partitions.length)
    : RDD[(K, V)] = self.withScope
{
  val part = new RangePartitioner(numPartitions, self, ascending)
  new ShuffledRDD[K, V, V](self, part)
    .setKeyOrdering(if (ascending) ordering else ordering.reverse)
}

从函数的实现可以看出,它主要接受两个函数,含义和sortBy一样,这里就不进行解释了。该函数返回的RDD一定是ShuffledRDD类型的,因为对源RDD进行排序,必须进行Shuffle操作,而Shuffle操作的结果RDD就是ShuffledRDD。其实这个函数的实现很优雅,里面用到了RangePartitioner,它可以使得相应的范围Key数据分到同一个partition中,然后内部用到了mapPartitions对每个partition中的数据进行排序,而每个partition中数据的排序用到了标准的sort机制,避免了大量数据的shuffle。


Scala版本案例

def sortByKey(): Unit = {
  val conf = new SparkConf().setMaster("local").setAppName("sortBy")
  val sc = new SparkContext(conf)
  val rdd = sc.makeRDD(List((11,0),(10,5),(4,2),(6,1),(20,2),(8,0)))

  val res =rdd.sortByKey(true,1)
  res.foreach(x => print(x + " "))
}

结果:(4,2) (6,1) (8,0) (10,5) (11,0) (20,2)


上面对Key进行了排序。细心的读者可能会问,sortBy函数中的第一个参数可以对排序方式进行重写。为什么sortByKey没有呢?难道只能用默认的排序规则。不是,是有的。其实在OrderedRDDFunctions类中有个变量ordering它是隐形的:
private val ordering = implicitly[Ordering[K]]
他就是默认的排序规则,我们可以对它进行重写,如下:

def sortByKey(): Unit = {
  val conf = new SparkConf().setMaster("local").setAppName("sortBy")
  val sc = new SparkContext(conf)
  val rdd = sc.makeRDD(List((11,0),(10,5),(4,2),(6,1),(20,2),(8,0)))
  //重写ordering
  implicit val sortIntegersByString = new Ordering[Int]{
    override def compare(x: Int, y: Int): Int = x.toString.compareTo(y.toString)
  }
  val res =rdd.sortByKey(true,1)
  res.foreach(x => print(x + " "))
}

结果:(10,5) (11,0) (20,2) (4,2) (6,1) (8,0)


Java版本案例

源码

def sortByKey(comp: Comparator[K], ascending: Boolean, numPartitions: Int): JavaPairRDD[K, V] = {
  implicit val ordering = comp // 允许比较器隐式转换为排序。
  fromRDD(new OrderedRDDFunctions[K, V, (K, V)](rdd).sortByKey(ascending, numPartitions))
}

def sortByKey(comp: Comparator[K], ascending: Boolean, numPartitions: Int): JavaPairRDD[K, V]
def sortByKey(comp: Comparator[K], ascending: Boolean): JavaPairRDD[K, V]
def sortByKey(comp: Comparator[K]): JavaPairRDD[K, V]
def sortByKey(ascending: Boolean, numPartitions: Int): JavaPairRDD[K, V]
def sortByKey(ascending: Boolean): JavaPairRDD[K, V]
def sortByKey(): JavaPairRDD[K, V]


public static void sortByKey() {
    SparkConf conf = new SparkConf().setAppName("sortBy").setMaster("local");
    JavaSparkContext sc = new JavaSparkContext(conf);
    List<Tuple2<String, Integer>> scoreList = Arrays.asList(
            new Tuple2<String, Integer>("1", 90),
            new Tuple2<String, Integer>("2", 60),
            new Tuple2<String, Integer>("21", 60),
            new Tuple2<String, Integer>("3", 50)
    );

    JavaPairRDD<String, Integer> pairRDD = sc.parallelizePairs(scoreList);

    // 自定义比较器:直接这样在内部定义是不正确的
    // 抛出异常Task not serializable: java.io .NotSerializableException:
    // 解决办法,另外定义一个小class ,implements Comparator<String>,Serializable

/*      
    Comparator<String> comparator = new Comparator<String>() {
        @Override
        public int compare(String o1, String o2) {
            return Integer.valueOf(o1).compareTo(Integer.valueOf(o2));
        }
    };
*/
    JavaPairRDD<String, Integer> res = pairRDD.sortByKey();
    //JavaPairRDD<String, Integer> res = pairRDD.sortByKey(new MyComparator());

    res.foreach(x -> System.out.print(x + " "));
    sc.close();
}

自定义比较器:

public class MyComparator implements Comparator<String>,Serializable {
    @Override
    public int compare(String o1, String o2) {
        return Integer.valueOf(o1).compareTo(Integer.valueOf(o2));
    }
}

不使用比较器结果:(1,90) (2,60) (21,60) (3,50)
使用比较器结果:(1,90) (2,60) (21,60) (3,50)


二次排序

Spark Java 二次排序

Spark Scala 二次排序

Spark: sortBy sortByKey 二次排序 Sample data(考场号,班级号,学号)–> 考场号升序,班级号升序,学号降序1 1 3 1 1 4 1 2 8 1 3 7 3 2 9 3 5 11 1 4 13 1 5 12 2 1 14 2 1 10 2 4 1 2 3 5 2 4 6 3 5 2 3 2 15 1 1 16 2 2 17 3 3 18 2 2 19 3 3 20sortBypackage com.spark.sort 阅读详情

相关推荐

SparksortByKey算子详解介绍

前面几篇文章讲过 `sortBy` 如何对RDD中元素进行排序,对于sortBy可以处理任何类型,单值类型或者键值类型都可以,不过本文将讲解另外一个算子 `sortByKey` ,该算子仅支持键值类型。

CSDN 精品推荐 732

java sortby_Spark排序SortBy

sortBy函数源码:接收三个参数,第一个参数必须,第二个和第三个参数非必要defsortBy[K](f:(T)=>K,ascending:Boolean=true,numPartitions:Int=this.partitions.length)(implicitord:Ordering[K],ctag:ClassTag[K]):RDD[T]=withSc...

weixin_30799553的博客 1361

Spark 算子sortBy使用

Spark 算子sortBy使用

congge_study的博客 2228

spark java sortby_【Spark Java API】Transformation(9)—sortByKey、repartitionAndSortWithinPartitions...

sortByKey官方文档描述:Sort the RDD by key, so that each partition contains a sorted range of the elements in ascending order.Calling `collect` or `save` on the resulting RDD will return or output an ordered...

weixin_39552204的博客 288

java 二次排序_【sparksortByKey实现二次排序

最近在项目中遇到二次排序的需求,和平常开发spark的application一样,开始查看API,编码,调试,验证结果。由于之前对spark的API使用过,知道API中的sortByKey()可以自定义排序规则,通过实现自定义的排序规则来实现二次排序。这里为了说明问题,举了一个简单的例子,key是由两部分组成的,我们这里按key的第一部分的降序排,key的第二部分升序排,具体如下:JavaSpar...

weixin_35129495的博客 406

sparkSortBySortByKey

sortBy函数 sortBy函数是在org.apache.spark.rdd.RDD类中实现的。 该函数有三个参数:   第一个参数是一个函数,该函数的也有一个带T泛型的参数,返回类型和RDD中元素的类型是一致的;   第二个参数是ascending,从字面的意思大家应该可以猜到,这参数决定排序后RDD中的元素是升序还是降序,默认是true,也就是升序;   第三个参数是numPartition...

TylerPY的博客 2032

Spark中RDD的sortBy排序的5种实现方法

在RDD,ortBy可以指定对键还是value进行排序sortBy可以通过下面5中方式实现排序 假如数据的格式如下,list中元素中分别为名称、单价、数量,字符之间用空格连接,要实现按照单价和数量降序 val products = sc.parallelize(List("A 100 10","B 200 20","C 200 30","D 400 30")) 1.通过Tuple方式,按照...

muyingmiao的专栏 1万+

Spark算子学习之四、其他算子

双value算子

comeOnBaby126的博客 379

图解Spark排序算子sortBy的核心源码

图解Spark排序算子sortBy的核心源码

朱季谦 1767

spark 二次排序两种方法(scala)

排序数据: aa 34 bb 24 cc 83 aa 53 cc 12 aa 47 bb 35 aa 21 cc 64 bb 73 第一种方法是用spark中的sortBy方法: 首先将数据处理成(“aa”,34)的格式; 然后使用sortBy算子进行排序; /** * 二次排序使用sortBy */ rdd.map(a =&gt; (a.split(" ")(0),a.split...

maenlai0086的博客 980

Spark 使用sortByKey进行二次排序

转载地址:https://blog.csdn.net/dwb1015/article/details/52207945 SparksortByKey API允许自定义排序规则,这样就可以进行自定义的二次排序、三次排序等等。  先来看一下sortByKey源码实现: def sortByKey(): JavaPairRDD[K, V] = sortByKey(true) def sort...

learn_tech的博客 769

spark 2.2.0源码解读(一) rdd源码解读

spark 2.2.0源码解读(一) rdd源码解读 spark中有很多rdd,每个rdd都有自己的作用,恰当用好rdd可以达到事半功倍的效果. 闲话少说,直接上代码 cache /** * Persist this RDD with the default storage level (`MEMORY_ONLY`). * 持久化RDD使用默认的存储级别(`MEMORY_ONLY`...

qq_16234927的博客 382

sparksortByKey实现二次排序

spark 二次排序

小飞侠的专栏 3666

Spark: sortBysortByKey函数详解

在很多应用场景都需要对结果数据进行排序Spark中有时也不例外。在Spark中存在两种对RDD进行排序的函数,分别是 sortBysortByKey函数。sortBy是对标准的RDD进行排序,它是从Spark 0.9.0之后才引入的(可以参见SPARK-1063)。而sortByKey函数是对PairRDD进行排序,也就是有Key和Value的RDD。下面将分别对这两个函数的实现以及使用进行说...

hellojoy的博客 2万+

SparksortByKeysortBy对(key,value)数据分别 根据key和value排序

SparksortByKeysortBy对(key,value)数据分别 根据key和value排序

dai451954706的专栏 3万+

spark函数sortByKey实现二次排序

最近在项目中遇到二次排序的需求,和平常开发spark的application一样,开始查看API,编码,调试,验证结果。由于之前对spark的API使用过,知道API中的sortByKey()可以自定义排序规则,通过实现自定义的排序规则来实现二次排序。 这里为了说明问题,举了一个简单的例子,key是由两部分组成的,我们这里按key的第一部分的降序排,key的第二部分升序排,具体如下: ...

weixin_30411997的博客 168

sparksortBy分区数

sparksortBy既是转换算子又是行动算子。 scala> sc.makeRDD(1 to 5, 2).sortBy(x=>x, false, 4) res11: org.apache.spark.rdd.RDD[Int] = MapPartitionsRDD[13] at sortBy at <console>:25 对应的UI界面是 可以看到出现了一个job,而行动算子才会产生job。点进job去之后,看到下幅图。 从图中可以看出,sortBy排序后产生的RDD的分区数

weixin_42307036的博客 2114
上一篇: 星型模型和雪花型模型比较
下一篇: Spark Java sortByKey二次排序及Task not serializable异常
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

生命不息丶折腾不止

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值