Mapreduce的排序、全排序以及二次排序

一:背景

Hadoop中虽然有自动排序和分组,由于自带的排序是按照Key进行排序的,有些时候,我们希望同时对Key和Value进行排序。自带的排序功能就无法满足我们了,还好Hadoop提供了一些组件可以让开发人员进行二次排序。

 

二:技术实现

我们先来看案例需求

#需求1: 首先按照第一列数字升序排列,当第一列数字相同时,第二列数字也升序排列(列之间用制表符\t隔开)

 

 
  1. 3 3

  2. 3 2

  3. 3 1

  4. 2 2

  5. 2 1

  6. 1 1

MapReduce计算之后的结果应该是:

 

 

 
  1. 1 1

  2. 2 1

  3. 2 2

  4. 3 1

  5. 3 2

  6. 3 3


#需求2:第一列不相等时,第一列按降序排列,当第一列相等时,第二列按升序排列

 

 

 
  1. 3 3

  2. 3 2

  3. 3 1

  4. 2 2

  5. 2 1

  6. 1 1

MapReduce计算之后的结果应该是:

 
  1. 3 1

  2. 3 2

  3. 3 3

  4. 2 1

  5. 2 2

  6. 1 1



下面是实现代码,实现两种需求的关键是compareTo()方法的实现不同:

 


public class SecondSortTest {// 定义输入路径private static final String INPUT_PATH = "hdfs://liaozhongmin:9000/data";// 定义输出路径private static final String OUT_PATH = "hdfs://liaozhongmin:9000/out";public static void main(String[] args) {try {// 创建配置信息Configuration conf = new Configuration();/**********************************************///对Map端输出进行压缩//conf.setBoolean("mapred.compress.map.output", true);//设置map端输出使用的压缩类//conf.setClass("mapred.map.output.compression.codec", GzipCodec.class, CompressionCodec.class);//对reduce端输出进行压缩//conf.setBoolean("mapred.output.compress", true);//设置reduce端输出使用的压缩类//conf.setClass("mapred.output.compression.codec", GzipCodec.class, CompressionCodec.class);// 添加配置文件(我们可以在编程的时候动态配置信息,而不需要手动去改变集群)/** conf.addResource("classpath://hadoop/core-site.xml");* conf.addResource("classpath://hadoop/hdfs-site.xml");* conf.addResource("classpath://hadoop/hdfs-site.xml");*/// 创建文件系统FileSystem fileSystem = FileSystem.get(new URI(OUT_PATH), conf);// 如果输出目录存在,我们就删除if (fileSystem.exists(new Path(OUT_PATH))) {fileSystem.delete(new Path(OUT_PATH), true);}// 创建任务Job job = new Job(conf, SecondSortTest.class.getName());//1.1 设置输入目录和设置输入数据格式化的类FileInputFormat.setInputPaths(job, INPUT_PATH);job.setInputFormatClass(TextInputFormat.class);//1.2 设置自定义Mapper类和设置map函数输出数据的key和value的类型job.setMapperClass(MySecondSortMapper.class);job.setMapOutputKeyClass(CombineKey.class);job.setMapOutputValueClass(LongWritable.class);//1.3 设置分区和reduce数量(reduce的数量,和分区的数量对应,因为分区为一个,所以reduce的数量也是一个)job.setPartitionerClass(HashPartitioner.class);job.setNumReduceTasks(1);//1.4 排序、分组//1.5 归约//2.1 Shuffle把数据从Map端拷贝到Reduce端。//2.2 指定Reducer类和输出key和value的类型job.setReducerClass(MySecondSortReducer.class);job.setOutputKeyClass(LongWritable.class);job.setOutputValueClass(LongWritable.class);//2.3 指定输出的路径和设置输出的格式化类FileOutputFormat.setOutputPath(job, new Path(OUT_PATH));job.setOutputFormatClass(TextOutputFormat.class);// 提交作业 退出System.exit(job.waitForCompletion(true) ? 0 : 1);} catch (Exception e) {e.printStackTrace();}}public static class MySecondSortMapper extends Mapper<LongWritable, Text, CombineKey, LongWritable>{//定义联合的keyprivate CombineKey combineKey = new CombineKey();protected void map(LongWritable key, Text value, Mapper<LongWritable, Text, CombineKey, LongWritable>.Context context) throws IOException,InterruptedException {//对输入的value进行切分String[] splits = value.toString().split("\t");//设置联合的keycombineKey.setComKey(Long.parseLong(splits[0]));combineKey.setComVal(Long.parseLong(splits[1]));//通过context写出去context.write(combineKey, new LongWritable(Long.parseLong(splits[1])));}}public static class MySecondSortReducer extends Reducer<CombineKey, LongWritable, LongWritable, LongWritable>{@Overrideprotected void reduce(CombineKey combineKey, Iterable<LongWritable> values, Reducer<CombineKey, LongWritable, LongWritable, LongWritable>.Context context)throws IOException, InterruptedException {//因为输入的CombineKey已经排好序了,所有我们只要获取其中的两个成员变量写出去就可以了。values在这个例子中没有什么作用context.write(new LongWritable(combineKey.getComKey()), new LongWritable(combineKey.getComVal()));}}}/*** 重新组合成一个key,实现二次排序* @author 廖*民* time : 2015年1月18日下午7:27:52* @version*/class CombineKey implements WritableComparable<CombineKey>{public long comKey;public long comVal;//必须提供无参构造函数,否则hadoop反射机制会出错public CombineKey() {}//有参构造函数public CombineKey(long comKey, long comVal) {this.comKey = comKey;this.comVal = comVal;}public long getComKey() {return comKey;}public void setComKey(long comKey) {this.comKey = comKey;}public long getComVal() {return comVal;}public void setComVal(long comVal) {this.comVal = comVal;}public void write(DataOutput out) throws IOException {out.writeLong(comKey);out.writeLong(comVal);}public void readFields(DataInput in) throws IOException {this.comKey = in.readLong();this.comVal = in.readLong();}/*** 这个方法一定要实现* java里面排序默认是小的放在前面,即返回负数的放在前面,这样就是所谓的升序排列* 我们在下面的方法中直接返回一个差值,也就相当于会升序排列。* 如果我们要实现降序排列,那么我们就可以返回一个正数*//*public int compareTo(CombineKey o) {//第一列不相同时按升序排列,当第一列相同时第二列按升序排列long minus = this.comKey - o.comKey;//如果第一个值不相等时,我们就先对第一列进行排序if (minus != 0){return (int) minus;}//如果第一列相等时,我们就对第二列进行排序return (int) (this.comVal - o.comVal);}*//*** 为了实现第一列不同时按降序排序,第一列相同时第二列按升序排列* 第一列:降序,当第一列相同时,第二列:升序* 为了实现降序,*/public int compareTo(CombineKey o) {//如果a-b<0即,a小于b,按这样 的思路应该是升序排列,我们可以返回一个相反数使其降序long tmp = this.comKey - o.comKey;//如果第一个值不相等时,我们就先对第一列进行排序if (tmp != 0){return (int) (-tmp);}//如果第一列相等时,我们就对第二列进行升序排列return (int) (this.comVal - o.comVal);}@Overridepublic int hashCode() {final int prime = 31;int result = 1;result = prime * result + (int) (comKey ^ (comKey >>> 32));return result;}@Overridepublic boolean equals(Object obj) {if (this == obj)return true;if (obj == null)return false;if (getClass() != obj.getClass())return false;CombineKey other = (CombineKey) obj;if (comKey != other.comKey)return false;return true;}}
 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/547309.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

webstorm使用技巧

WebStorm快捷键收集&#xff1a;模式visual studio 代码提示&#xff1a;ctrl alt 空格 代码补全&#xff1a;alt / 代码换行&#xff1a;ctrl shift 上下箭头 重新运行&#xff1a;ctrl F5 最近使用试图&#xff1a;ctrl E 围绕包裹代码&#xff1a; ctrl alt …

iOS7时代我们用什么来追踪和识别用户?

要识别用户&#xff0c;首先就是要选择一个标识符&#xff0c;通过这个标识符来识别这个用户的设备&#xff08;而不是用户&#xff09;&#xff0c;这个标识符要能够保证一个设备上返回的值是一样的&#xff0c;并且在其他设备上不会出现相同的值。 在iOS7之前&#xff0c;曾经…

Python爬虫淘宝商品详情页价格、类似数据

在讲爬取淘宝详情页数据之前&#xff0c;先来介绍一款 Chrome 插件&#xff1a;Toggle JavaScript (它可以选择让网页是否显示 js 动态加载的内容)&#xff0c;如下图所示&#xff1a; 当这个插件处于关闭状态时&#xff0c;待爬取的页面显示的数据如下: 当这个插件处于打开状态…

js提取正则中的字符串

代码如下&#xff1a; var results data.match(/(start).*?()/);if (results ! null){console.log(data[0]);}

微信公众号开发(—)接口与服务器关联

微信公众号开发(—) 以下都是借鉴的微信公众平台的文档加老师指点和自行的理解。 1.一台有微信的手机.(别问我老人机可以不 有微信就可以&#xff01;&#xff01;&#xff01;) 2.需要有一个微信公众平台的测试号&#xff08;订阅号,服务号也可以按自己需求来&#xff09;. 3.…

让zabbix图像中文不再是乱码

默认的&#xff0c;如果想要给zabbix的图像起个中文名&#xff0c;那么当你兴致勃勃的看图像时&#xff0c;会发现中文的地方都是乱码。怎么办呢&#xff1f;首先&#xff0c;从你的windows机器的控制面板—字体中选择一个中文字符集&#xff0c;然后上传至zabbix服务器的wwwro…

nodejs支持ssi实现include shtml页面

express 对于include的代码默认不处理&#xff0c;直接输出&#xff0c;没办法执行include的内容&#xff0c;但可以通过Nginx实现。 1、 配置nginx设置开启ssi模式。 server {…ssi on;ssi_silent_errors on;ssi_types text/shtml;… 2、添加include页面 <!--# include vi…

Windows PC软件反编译逆向破解

文章目录 一.OllyDbg工具简介二.OllyDbg分析Crakeme示例1三.OllyDbg分析Crakeme示例2四.总结作者的github资源&#xff1a; 系统安全&#xff1a;https://github.com/eastmountyxz/SystemSecurity-ReverseAnalysis网络安全&#xff1a;https://github.com/eastmountyxz/Networ…

微信公众号天气与聊天机器人小功能

微信公众号小功能 以下都是借鉴的微信公众平台的文档加老师指点和自行的理解。 &#xff08;1&#xff09;微信公众号发送地区回复现在和未来五天天气情况 &#xff08;2&#xff09;发送语音和智能机器人聊天 一、调用天气预报接口 实现微信公众号发送地区回复现在和未来五天…

如何实现:判断数据库中某表是否有记录,若为空,则插入一条记录。若不为空则查询某记录...

select count(*) as num1 from tableif num1 0insert into ...elseselect * from table.... SQL的过程如下&#xff1a;Select top 1 * from tableif rowcount>0 --上一次影响条数 insert into Table --插入语句else Select * from Table --查询转载于:https:/…

安卓app逆向破解脱壳教程

From&#xff1a;Hook 神器家族的 Frida 工具使用详解&#xff1a;https://blog.csdn.net/FlyPigYe/article/details/90258758 详解 Hook 框架 frida ( 信抢红包 )&#xff1a;https://www.freebuf.com/company-information/180480.html APP逆向神器之Frida【Android初级篇】…

nodejs生成多层目录和生成文件的通用方法

/***生成多层目录* param dir 多层目录* param split 分隔符&#xff0c;ex:/ 对应的目录地址:2015/10/10* param mode 目录权限&#xff08;读写权限&#xff09;&#xff0c;默认0777* param callback*/var createDirsSync function (dir, split, mode, callback) {console.…

关注微信公众号使其自动发送欢迎你关注消息

关注微信公众号使其自动发送欢迎你关注消息 一般我们关注微信公众号时。他都会自动推送一条消息。欢迎您关注了某公众号。而今天我们所做的就是这个功能。 关注公众号时我们需要获取到用户的一些个人基本信息。 而获取基本信息就要看他的运行原理。到底是怎么运行。 当我们申请…

微信公众号——永久素材的上传

微信公众号永久素材的上传 思路&#xff1a;1.需要上传到本地&#xff08;因为后面需要用的本地的绝对路径 2.上传到微信服务器 3.添加信息到本地数据库 一、上传图片到本地 文件上传的方法 以下是我的代码 首先更改文件上传的配置 而后写我们的文件上传方法 if (request…

nodejs在Liunx上的部署生产方式-PM2

先安装&#xff1a;npm install -g pm2 &#xff08;注意&#xff1a;使用它要先安装它&#xff0c;用root账号和全局模式安装一下&#xff09; 安装完成使用&#xff1a;pm2 -v 查看版本信息 安装成功之后&#xff0c;启动nodejs项目&#xff1a;pm2 start app.js --项目名…

安卓逆向之基于Xposed-ZjDroid脱壳 逆向分析(脱壳)

安卓逆向——某力播逆向分析(脱壳) 一、环境 这一步真的头疼&#xff0c;环境很重要&#xff0c;各种测试&#xff0c;一下是我测试的环境&#xff0c;由于没有真机&#xff0c;就拿虚拟机做测试 1. Xposed 2. FDex2 3. fiddler 4. 软件 二、抓包 通过 …

nginx php mysql一些常用命令(windows linux)

Nginx(nginx) 通常安装路径 /usr/local/nginx检查Nginx是否运行 ps aux | grep nginx重启Nginx /usr/local/nginx/sbin/nginx -s reload停止Nginx /usr/local/nginx/sbin/nginx -s stop测试配置 /usr/local/nginx/sbin/nginx -tPHP(php) PHP安装路径 /usr/local/php查看PH…

nodejs图片转换字节保存

fs.readFile(上传图片路径, function(err, data) {if (err) {// 错误处理return;}var base64str new Buffer(data).toString(base64); // 图片转换为字节fs.writeFileSync(copy.jpg, base64str); // 字节流保存为图片});

Apache/Tomcat/JBOSS/Nginx(2)

三.性能测试&#xff1a;将分别测试3种软件在对动态页面和静态页面请求及并发时的响应时间l 静态页面搜狐首页LIGHTTPDn/-c(ab参数)cpu%MemRequestsperSecondTime taken for tests100000/1006460462.7521.6100000/2006760312.0732.4100000/5008360137.2472.8100000/1000出现错误…

安卓逆向代码反混淆 Simplify工具 JEB2反混淆神器

【技术分享】Android程序反混淆利器——Simplify工具 https://www.anquanke.com/post/id/85388 发布时间&#xff1a;2017-01-23 17:21:23 问题背景 Android程序代码混淆是Android开发者经常用来防止app被反编译之后迅速被分析的常见手法。在没有混淆的代码中&#xff0c;被…