一、Spark二次排序的概念
- 排序操作是数据处理过程中的常用操作步骤,Spark提供了诸如sortBy算子和sortByKey算子来实现排序,但是存在一些不足的地方,此类算子只能针对一个排序的依据进行排序,比如说sortByKey算子仅仅只能根据Key来排序,而Key常常只是一个数字或者字符串,现给出这样的一个需求(以下的演示也是围绕这个需求),给出学生数据,里面有数学和语文两门成绩,按数学成绩升序排序,如果数学成绩相同,再按语文成绩升序排序,这里涉及到了同时对两个排序字段进行排序,因而直接使用以上的那些算子是不能实现的,而实际生产中排序字段只会更多甚至10几个,因此就要使用Spark核心编程的较为高阶的技术二次排序了。
- Spark二次排序本质上是自定义Key来实现排序,使用一个Bean将所有的要排序的字段封装进Bean中,然后在Bean自定义排序规则,最后结合sortBy算子或者sortByKey算子操作自定义的Key即可实现Spark的二次排序。
二、实现二次排序的详细步骤(Java语言)
- 创建一个JavaBean,将涉及排序的字段封装进JavaBean,中比如说上述需求的数学成绩与语文成绩就是待排序字段,然后为排序字段增添getter和setter方法。
- 实现Java序列化接口Serializable,因为要被Spark直接引用所以自定义的引用类型都必须序列化,而Spark支持Java的序列化。
- 实现Ordered接口,其泛型类型就是当前JavaBean。然后重写接口方法:
(1).大于方法:$greater
(2).大于或等于方法:$greater$eq
(3).小于方法:$less
(4).小于或等于方法:$less$eq
(5).重写compare和compareTo方法
实际上,上述5类方法涵盖了两个待比较Key的所有比较结果,Spark会依次调用上述方法,直到产生一个比较结果就会跳出比较。 - 将自定义的JavaBean作为Key使用sorkByKey算子进行排序,sorkByKey算子会根据我们的自定义排序规则对Key进行排序。
三、二次排序代码演示
1.Java版本
- 创建类SecondlySortKeyJava,用于封装待排序的字段,并实现Order接口,实现接口方法:
/** * 定义二次排序的key,即实现Ordered接口 * 另外因为这个Key需要被算子引用所以需要序列化 * 常见的方法是实现Java的Serializable * 或者使用Kryo序列化 */ public class SecondlySortKeyJava implements Ordered<SecondlySortKeyJava>, Serializable { private int math; private int chinese; // 定义有参构造方法 public SecondlySortKeyJava(int manth, int chinese) { this.math = manth; this.chinese = chinese; } // 定义相等规则 public int compare(SecondlySortKeyJava other) { if(this.math - other.math != 0) return this.math - other.math; else if(this.chinese - other.chinese != 0){ return this.chinese - other.chinese; } return 0; } // 定义小于规则 public boolean $less(SecondlySortKeyJava other) { if(this.math < other.getManth()){ return true; }else if(this.math == other.getManth