hadoop提交作业自定义排序和分组
现有数据如下:
3 3
3 2
3 1
2 2
2 1
1 1
要求为:
先按第一列从小到大排序,如果第一列相同,按第二列从小到大排序
如果是hadoop默认的排序方式,只能比较key,也就是第一列,而value是无法参与排序的
这时候就需要用到自定义的排序规则
解决思路:
自定义数据类型,将原本的key和value都包装进去
将这个数据类型当做key,这样就比较key的时候就可以包含第一列和第二列的值了
自定义数据类型NewK2如下:
//要实现自定义的排序规则必须实现WritableComparable接口,泛型参数为类本身 public class NewK2 implements WritableComparable<NewK2> { //代表第一列和第二列的数据 Long first; Long second; public NewK2() { } public NewK2(long first, long second) { this.first = first; this.second = second; } //重写序列化和反序列化方法 @Override public void readFields(DataInput in) throws IOException { this.first = in.readLong(); this.second = in.readLong(); } @Override public void write(DataOutput out) throws IOException { out.writeLong(first); out.writeLong(second); } //当k2进行排序时,会自动调用该方法. 当第一列不同时,升序;当第一列相同时,第二列升序 //如果希望降序排列,那么只需要对调this对象和o对象的顺序 @Override public int compareTo(NewK2 o) { if(this.first != o.first) { return (int)(this.first - o.first); } else { return (int) (this.second - o.second); } } //重写hashCode和equals方法 @Override public int hashCode() { return this.first.hashCode() + this.second.hashCode(); } @Override public boolean equals(Object obj) { if (!(obj instanceof NewK2)) { return false; } NewK2 oK2 = (NewK2) obj; return (this.first == oK2.first) && (this.second == oK2.second); } }
public class MyMapper extends Mapper<LongWritable, Text, NewK2, LongWritable> { protected void map( LongWritable key, Text value, org.apache.hadoop.mapreduce.Mapper<LongWritable, Text, NewK2, LongWritable>.Context context) throws java.io.IOException, InterruptedException { final String[] splited = value.toString().split("\t"); //分割完成之后的数据如:3,1 分别赋值给k2对象的first和second属性 final NewK2 k2 = new NewK2(Long.parseLong(splited[0]), Long.parseLong(splited[1])); final LongWritable v2 = new LongWritable(Long.parseLong(splited[1])); //将k2当做key输出,这样在排序的时候就会调用NewK2的compareTo方法,里面写的是我们自己的排序规则 context.write(k2, v2); }; }
public class MyReducer extends Reducer<NewK2, LongWritable, LongWritable, LongWritable> { protected void reduce( NewK2 k2, java.lang.Iterable<LongWritable> v2s, org.apache.hadoop.mapreduce.Reducer<NewK2, LongWritable, LongWritable, LongWritable>.Context context) throws java.io.IOException, InterruptedException { context.write(new LongWritable(k2.first), new LongWritable( k2.second)); }; }
MySubmit类的代码和之前的一样无需改动
运行可得到结果如下图:
如果业务需求又发生了改变,如:上图结果中,第一列相同的,只要列出第二列的值最小的那个选项即可
那么结果应该为
1 1
2 1
3 1
可是我们之前使用的是自定义的数据类型当做key
而hadoop默认的分组策略是所有key相同的选项当做一组
而两个NewK2对象要相等,就必须要first和second属性都相等才行
这时就需要用到自定义的分组策略
自定义分组类如下:
//自定义的分组类必须实现RawComparator,泛型参数为类本身 public class MyGroupingComparator implements RawComparator<NewK2> { //重写两个比较方法 //按对象进行比较,规定只要两个NewK2对象的first属性相同就视为相等 @Override public int compare(NewK2 o1, NewK2 o2) { return (int) (o1.first - o2.first); } /** * @param arg0 * 表示第一个参与比较的字节数组 * @param arg1 * 表示第一个参与比较的字节数组的起始位置 * @param arg2 * 表示第一个参与比较的字节数组的偏移量 * * @param arg3 * 表示第二个参与比较的字节数组 * @param arg4 * 表示第二个参与比较的字节数组的起始位置 * @param arg5 * 表示第二个参与比较的字节数组的偏移量 */ @Override public int compare(byte[] arg0, int arg1, int arg2, byte[] arg3, int arg4, int arg5) { return WritableComparator .compareBytes(arg0, arg1, 8, arg3, arg4, 8); } }
在MySubmit代码中加入设置分组策略
// 1.4 TODO 排序、分区 job.setGroupingComparatorClass(MyGroupingComparator.class);
再次运行程序可得到如下图的结果: 
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
在hadoop作业中自定义分区和归约
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq1010885678/article/details/43735703 当遇到有特殊的业务需求时,需要对hadoop的作业进行分区处理 那么我们可以通过自定义的分区类来实现 还是通过单词计数的例子,JMapper和JReducer的代码不变,只是在JSubmit中改变了设置默认分区的代码,见代码: //1.3分区 //设置自定义分区类 job.setPartitionerClass(JPartitioner.class); //设置分区个数--这里设置成2,代表输出分为2个区,由两个reducer输出 job.setNumReduceTasks(2); 自定义的JPartitioner代码如下: import org.apache.hadoop.io.LongWritable; import org.apache.hadoop.io.Text; import org.apache.hadoop.mapreduce.lib.partition.HashPartitioner; //自定义...
- 下一篇
HADOOP再进阶:本地Yum软件源安装Cloudera Manager 5
参考URL: http://blog.csdn.net/yangzhaohui168/article/details/30118175 http://blog.csdn.net/yangzhaohui168/article/details/33403555
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS7,CentOS8安装Elasticsearch6.8.6
- SpringBoot2整合Redis,开启缓存,提高访问速度
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- Hadoop3单机部署,实现最简伪集群
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- SpringBoot2全家桶,快速入门学习开发网站教程
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- 设置Eclipse缩进为4个空格,增强代码规范