回顾Map阶段四大步骤

  首先,我们回顾一下在MapReduce中,排序和分组在哪里被执行:

map stage

  从上图中可以清楚地看出,在Step1.4也就是第四步中,需要对不同分区中的数据进行排序和分组,默认情况下,是按照key进行排序和分组。

1.2 实验场景数据文件

  在一些特定的数据文件中,不一定都是类似于WordCount单次统计这种规范的数据,比如下面这类数据,它虽然只有两列,但是却有一定的实践意义。

3 3
3 2
3 1
2 2
2 1
1 1

  (1)如果按照第一列升序排列,当第一列相同时,第二列升序排列,结果如下所示

1 1
2 1
2 2
3 1
3 2
3 3

  (2)如果当第一列相同时,求出第二列的最小值,结果如下所示

3 1
2 1
1 1

  接着,我们会针对这个数据文件,进行排序和分组的实践尝试,以求达到结果所示的效果。

二、初步探索排序

2.1 默认的排序

  在Hadoop默认的排序算法中,只会针对key值进行排序,我们最初的代码如下(这里只展示了map和reduce函数):

复制代码
public class MySortJob extends Configured implements Tool {

public static class MyMapper extendsMapper<LongWritable, Text, LongWritable, LongWritable> {protected void map(LongWritable key,Text value,Mapper<LongWritable, Text, LongWritable, LongWritable>.Context context)throws java.io.IOException, InterruptedException {String[] spilted = value.toString().split("\t");long firstNum = Long.parseLong(spilted[0]);long secondNum = Long.parseLong(spilted[1]);context.write(new LongWritable(firstNum), new LongWritable(secondNum));};
}public static class MyReducer extendsReducer<Text, LongWritable, Text, LongWritable> {protected void reduce(LongWritable key,java.lang.Iterable<LongWritable> values,Reducer<LongWritable, LongWritable, LongWritable, LongWritable>.Context context)throws java.io.IOException, InterruptedException {for (LongWritable value : values) {context.write(key, value);}};
}

}

复制代码

  这里我们将第一列作为了key,第二列作为了value。

  可以查看一下运行后的结果,如下所示:

1 1
2 2
2 1
3 3
3 2
3 1

  从运行结果来看,并没有达到我们最初的目的,于是,我们需要抛弃默认的排序规则,因此我们要自定义排序。

2.2 自定义排序

  (1)封装一个自定义类型作为key的新类型:将第一列与第二列都作为key

复制代码
private static class MyNewKey implements WritableComparable {
long firstNum;
long secondNum;

    public MyNewKey() {}public MyNewKey(long first, long second) {firstNum = first;secondNum = second;}@Overridepublic void write(DataOutput out) throws IOException {out.writeLong(firstNum);out.writeLong(secondNum);}@Overridepublic void readFields(DataInput in) throws IOException {firstNum = in.readLong();secondNum = in.readLong();}/** 当key进行排序时会调用以下这个compreTo方法*/@Overridepublic int compareTo(MyNewKey anotherKey) {long min = firstNum - anotherKey.firstNum;if (min != 0) {// 说明第一列不相等,则返回两数之间小的数return (int) min;} else {return (int) (secondNum - anotherKey.secondNum);}}
}

复制代码

PS:这里为什么需要封装一个新类型呢?因为原来只有key参与排序,现在将第一个数和第二个数都参与排序,作为一个新的key。

  (2)改写最初的MapReduce方法函数代码:(只展示了map和reduce函数,还需要修改map和reduce输出的类型设置)

复制代码
public static class MyMapper extends
Mapper

当第一列相同时,求出第二列的最小值

3 3
3 2
3 1
2 2
2 1

1 1

预期结果应该是

3 1
2 1
1 1

复制代码

3.2 自定义分组

  为了针对新的key类型作分组,我们也需要自定义一下分组规则:

  (1)编写一个新的分组比较类型用于我们的分组:

复制代码
private static class MyGroupingComparator implements
RawComparator {

    /** 基本分组规则:按第一列firstNum进行分组*/@Overridepublic int compare(MyNewKey key1, MyNewKey key2) {return (int) (key1.firstNum - key2.firstNum);}/** @param b1 表示第一个参与比较的字节数组* * @param s1 表示第一个参与比较的字节数组的起始位置* * @param l1 表示第一个参与比较的字节数组的偏移量* * @param b2 表示第二个参与比较的字节数组* * @param s2 表示第二个参与比较的字节数组的起始位置* * @param l2 表示第二个参与比较的字节数组的偏移量*/@Overridepublic int compare(byte[] b1, int s1, int l1, byte[] b2, int s2, int l2) {return WritableComparator.compareBytes(b1, s1, 8, b2, s2, 8);}}

复制代码

  从代码中我们可以知道,我们自定义了一个分组比较器MyGroupingComparator,该类实现了RawComparator接口,而RawComparator接口又实现了Comparator接口,下面看看这两个接口的定义:

  首先是RawComparator接口的定义:

public interface RawComparator extends Comparator {
public int compare(byte[] b1, int s1, int l1, byte[] b2, int s2, int l2);
}

  其次是Comparator接口的定义:

public interface Comparator {
int compare(T o1, T o2);
boolean equals(Object obj);
}

  在MyGroupingComparator中分别对这两个接口中的定义进行了实现,RawComparator中的compare()方法是基于字节的比较,Comparator中的compare()方法是基于对象的比较。

  在基于字节的比较方法中,有六个参数,一下子眼花了:

Params:

  • @param arg0 表示第一个参与比较的字节数组
  • @param arg1 表示第一个参与比较的字节数组的起始位置
  • @param arg2 表示第一个参与比较的字节数组的偏移量
    • @param arg3 表示第二个参与比较的字节数组
  • @param arg4 表示第二个参与比较的字节数组的起始位置
  • @param arg5 表示第二个参与比较的字节数组的偏移量

      由于在MyNewKey中有两个long类型,每个long类型又占8个字节。这里因为比较的是第一列数字,所以读取的偏移量为8字节。

      (2)添加对分组规则的设置:

      // 设置自定义分组规则
    job.setGroupingComparatorClass(MyGroupingComparator.class);

      (3)现在看看运行结果:

参考资料

(1)吴超,《深入浅出Hadoop》:http://www.superwu.cn/

(2)Suddenly,《Hadoop日记Day18-MapReduce排序和分组》:http://www.cnblogs.com/sunddenly/p/4009751.html

MapReduce中的排序和分组相关推荐

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

    Hadoop学习笔记-11.MapReduce中的排序和分组 一.写在之前的 1.1 回顾Map阶段四大步骤 首先,我们回顾一下在MapReduce中,排序和分组在哪里被执行: 从上图中可以清楚地看出 ...

  2. SQL中的排序和分组

    SQL中的排序和分组 一.排序 order by 语法:select 字段 from 表名称 where 筛查条件 order by 排序字段列表(顺序不能乱)desc(ace) select * f ...

  3. mysql自定义函数分组_mysql中的排序和分组及分组函数

    现实中有很多这样的需求,对全班同学成绩进行排名,将所有的学生信息按照班级来分组,先将学生按班级分组再进行成绩排名等等.今天老韩就来介绍一下如何通过数据库的排序.分组.分组排序来实现这个需求(是排序,不 ...

  4. MapReduce中的排序(附代码)

    在直接学习hadoop的排序之前还要了解一些基本知识. Hadoop的序列化和比较接口 Hadoop的序列化格式:Writable Writable是Hadoop自己的序列化格式,还要一个子接口是Wr ...

  5. mysql分组语句的子句_MySQL 中的排序与分组 语句

    MySQL ORDER BY 排序 我们知道从 MySQL 表中使用 SQL SELECT 语句来读取数据,如果我们需要对读取的数据进行排序,我们就可以使用 MySQL 的 ORDER BY 子句来设 ...

  6. access 分组序号_二级Access数据库备考笔记之报表排序和分组

    时 间:2012-08-17 12:50:26 作 者:摘 要:二级Access数据库备考笔记之报表排序和分组 正 文: 报表排序和分组 缺省情况下,报表中的记录是按照自然顺序,即数据输入的先后顺序排 ...

  7. php如何对数组进行分组,如何在PHP中对数组进行分组排序

    如何在PHP中对数组进行分组排序 发布时间:2021-01-04 16:28:51 来源:亿速云 阅读:98 作者:Leah 这篇文章将为大家详细讲解有关如何在PHP中对数组进行分组排序,文章内容质量 ...

  8. Hadoop大数据——mapreduce中的Combiner/序列化/排序初步

    mapreduce中的Combiner (1)combiner是MR程序中Mapper和Reducer之外的一种组件 (2)combiner组件的父类就是Reducer (3)Combiner和red ...

  9. Linux 中使用 sort 指令分组排序详解

    Linux 中使用 sort 指令分组排序详解 sort 中进行分组排序主要用到的选项为 -k,此文,我们着重于该选项的使用方式,用到的其它选项不做解释,有兴趣的同学可以查看帮助文档 1. 数据准备 ...

  10. Java 8 辣么大(lambda)表达式不慌之—–(五)示例-Collectors中的统计、分组、排序等

    Java 8 辣么大(lambda)表达式不慌之-–(五)示例-Collectors中的统计.分组.排序等 summarizingInt 按int类型统计 maxBy取最大/minBy取最小 aver ...

最新文章

  1. 用JavaScript获取URL中的参数值
  2. 服务发现系统之consul入门
  3. Swift - 表格图片加载优化(拖动表格时不加载,停止时只加载当前页图片)
  4. 【CentOS】EOF使用
  5. Redis简介及安装
  6. visual studio 代码提示_《微软模拟飞行2020》代码暗示下一代Xbox或支持VR
  7. [转]Excel数据转化为sql脚本
  8. (简单) POJ 3984 迷宫问题,BFS。
  9. Java中的析构方法finalize
  10. RIP-OSPF-EIGRP 相互再发布
  11. kubernetes视频教程笔记 (6)-kubernetes集群安装
  12. 汉字转拼音类(多音字)
  13. 升压电路的原理-原文地址:http://www.52solution.com/basic/1218
  14. UDTF's are not supported outside the SELECT clause, nor nested in expressions (state=42000,code=1008
  15. 大数据薪水大概多少_大数据就业岗位有哪些?薪资多少?
  16. 大恒水星相机+opencv4.0.1保存视频
  17. Latex引用参考文献-BibTex的使用
  18. 信号系统中使用的继电器
  19. VOIP通信中Codec选择的几个时代。
  20. AudioManager音量控制

热门文章

  1. 题目:学习成绩 = 90分的同学用A表示,60 - 89分之间的用B表示,60分以下的用C表示
  2. 在你公司Code Review是一种形式,还是一种开发文化?
  3. C语言1379最小公倍数,求最小公倍数的三种方法
  4. ubuntu ble c语言编程,c – 如何在ubuntu上安装bluez进行开发?
  5. html的经典语法大全,HTML语法大全
  6. Tomcat配置两个应用服务
  7. cryptojs php 互通_如何实现PHP7和CryptoJS的AES加密方式互通?
  8. redis jar包_「建议收藏」手把手教你从零搭建一个redis服务
  9. 计算机专业范文推荐信,出国留学推荐信范文,计算机专业
  10. python数组下标用变量_你所不知道的Python奇技淫巧13招【实用】