现有数据如下:

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);
}
}

MyMapper类代码:

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);
};
}

MyReducer类代码:

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);

再次运行程序可得到如下图的结果:

hadoop提交作业自定义排序和分组的更多相关文章

  1. Hadoop提交作业流程

    一 .需要知道的内容 1.ResourceManager ------>yarn的老大 2.NodeManager        ------>yarn的小弟 3.ResourceMana ...

  2. 2 weekend110的hadoop的自定义排序实现 + mr程序中自定义分组的实现

    我想得到按流量来排序,而且还是倒序,怎么达到实现呢? 达到下面这种效果, 默认是根据key来排, 我想根据value里的某个排, 解决思路:将value里的某个,放到key里去,然后来排 下面,开始w ...

  3. Hadoop mapreduce自定义排序WritableComparable

    本文发表于本人博客. 今天继续写练习题,上次对分区稍微理解了一下,那根据那个步骤分区.排序.分组.规约来的话,今天应该是要写个排序有关的例子了,那好现在就开始! 说到排序我们可以查看下hadoop源码 ...

  4. Hadoop学习笔记—11.MapReduce中的排序和分组

    一.写在之前的 1.1 回顾Map阶段四大步骤 首先,我们回顾一下在MapReduce中,排序和分组在哪里被执行: 从上图中可以清楚地看出,在Step1.4也就是第四步中,需要对不同分区中的数据进行排 ...

  5. Hadoop学习之自定义二次排序

    一.概述    MapReduce框架对处理结果的输出会根据key值进行默认的排序,这个默认排序可以满足一部分需求,但是也是十分有限的.在我们实际的需求当中,往 往有要对reduce输出结果进行二次排 ...

  6. Hadoop学习之路(7)MapReduce自定义排序

    本文测试文本: tom 20 8000 nancy 22 8000 ketty 22 9000 stone 19 10000 green 19 11000 white 39 29000 socrate ...

  7. Hadoop【MR的分区、排序、分组】

    [toc] 一.分区 问题:按照条件将结果输出到不同文件中 自定义分区步骤 1.自定义继承Partitioner类,重写getPartition()方法 2.在job驱动Driver中设置自定义的Pa ...

  8. eclipse 提交作业到JobTracker Hadoop的数据类型要求必须实现Writable接口

    问:在eclipse中的写的代码如何提交作业到JobTracker中的哪?答:(1)在eclipse中调用的job.waitForCompletion(true)实际上执行如下方法 connect() ...

  9. 自定义排序及Hadoop序列化

    自定义排序 将两列数据进行排序,第一列按照升序排列,当第一列相同时,第二列升序排列. 在map和reduce阶段进行排序时,比较的是k2.v2是不参与排序比较的.如果要想让v2也进行排序,需要把k2和 ...

随机推荐

  1. servlet(4) - servletAPI - 小易Java笔记

    Servlet规范核心类图 1.请求和响应对象 ==> HTTP协议包含请求和响应部分. ==> HttpServletRequest就代表着请求部分 ==> HttpServlet ...

  2. Python 进阶 之 yield

    .转载自:https://www.ibm.com/developerworks/cn/opensource/os-cn-python-yield/ Python yield 使用浅析: 您可能听说过, ...

  3. JavaScript 之 定时器 延迟器

    1:setTimeout("function()",time) setTimeout("function()",time) 设置一个超时对象,执行到到该代码时会 ...

  4. docker rancher 安装

    1.rancher 中文文档 https://rancher.com/docs/rancher/v1.6/zh/ 2.从阿里云拉取镜像 docker pull registry.cn-hangzhou ...

  5. UESTC 30.最短路-最短路(Floyd or Spfa(链式前向星存图))

    最短路 Time Limit: 3000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others) 在每年的校赛里,所有进入决赛的同 ...

  6. MySQL密码不能登陆问题

        由于种种原因,在进行开发的时候我一直是基于Windows平台,并且以前初学的时候常常重装不同版本的 MySQL数据库.因此长时间不使用后就产生了一些冲突的问题.     简单描述下,今天用以前 ...

  7. 福州3中集训day5

    数论,zld神犇认为我们都学过数论的,讲了一波高端(入门?)操作,从扩展欧几里得开始,同余方程诸如此类,早晚得重修.连课件都没,拿着画图讲了一上午 sro_zld_orz 具体内容都记在本上. 还是说 ...

  8. leetcode83 Remove Duplicates from Sorted List

    题意:删掉单链表里重复的节点,如:Given 1->1->2, return 1->2.Given 1->1->2->3->3, return 1->2 ...

  9. [BZOJ 2817] 波浪

    Link: BZOJ 2817 传送门 Solution: 算是比较神的DP了吧, 首先这个绝对值处理起来很难受,肯定要想办法去掉 于是想到从小到大插入的方式,便不存在绝对值的问题了 插入一个数只有5 ...

  10. 【最近公共祖先】【树链剖分】CODEVS 1036 商务旅行

    树链剖分求lca模板.O(log(n)),就是不倍增嘛~ #include<cstdio> #include<algorithm> using namespace std; # ...