• 在map和reduce阶段进行排序时,比较的是k2。v2是不参与排序比较的。如果要想让v2也进行排序,需要把k2和v2组装成新的类,作为k2,才能参与比较。

例子:

二次排序:在第一列有序得到前提下第二列進行排序。

思路:先找<k3,v3>在找<k2,v2>之後的mapreduce就容易寫了

方法1:让输出的第一列作为k3,第二列作为v3    关键:输出的v3需要参与排序,此种方式无法实现二次排序

方法2:让1,2列只作为k3,而v3为空。(

方法3:有可能让k3为空,v3为第二列吗? 答案是不能的,假设k3为空,一般情况下k2也为空,则v2中存放的数据进入后每一组都会放入一个value中,目前没有遇到)

因此,只能选择方法二进行二次排序。

根据前面知识,关键思路:排序和分组是按照k2进行排序和分组的情形需铭记。

第一部分:分部代码

自定义排序:

 private static class TwoInt implements WritableComparable<TwoInt>{

     public int t1;
public int t2;
public void write(DataOutput out) throws IOException {
out.writeInt(t1);
out.writeInt(t2);
} public void set(int t1, int t2) {
this.t1=t1;
this.t2=t2;
} public void readFields(DataInput in) throws IOException {
this.t1=in.readInt();
this.t2=in.readInt();
} public int compareTo(TwoInt o) {
if (this.t1 ==o.t1) { //當第一列相等的時候,第二列升序排列
return this.t2 -o.t2;
}
return this.t1-o.t1;//當第一列不相等的時候,按第一列升序排列
} }

自定义Mapper类

 private static class MyMapper extends Mapper<LongWritable, Text, TwoInt, NullWritable>{
TwoInt K2 = new TwoInt();
@Override
protected void map(LongWritable key, Text value,
Mapper<LongWritable, Text, TwoInt, NullWritable>.Context context)
throws IOException, InterruptedException {
String[] splited = value.toString().split("\t");
K2.set(Integer.parseInt(splited[0]),Integer.parseInt(splited[1]));
context.write(K2, NullWritable.get());
}
}

自定义Reduce类

 //按照k2進行排序,分組,此數據分爲6組,在調用Reduce
private static class MyReducer extends Reducer<TwoInt, NullWritable, TwoInt, NullWritable>{
@Override
protected void reduce(TwoInt k2, Iterable<NullWritable> v2s,
Reducer<TwoInt, NullWritable, TwoInt, NullWritable>.Context context)
throws IOException, InterruptedException {
context.write(k2, NullWritable.get());
}
}

捆绑Map和Reduce在一起

 public static void main(String[] args) throws Exception {
Job job = Job.getInstance(new Configuration(), SecondarySortTest.class.getSimpleName());
job.setJarByClass(SecondarySortTest.class);
//1.自定义输入路径
FileInputFormat.setInputPaths(job, new Path(args[0]));
//2.自定义mapper
//job.setInputFormatClass(TextInputFormat.class);
job.setMapperClass(MyMapper.class);
//job.setMapOutputKeyClass(Text.class);
//job.setMapOutputValueClass(TrafficWritable.class); //3.自定义reduce
job.setReducerClass(MyReducer.class);
job.setOutputKeyClass(TwoInt.class);
job.setOutputValueClass(NullWritable.class);
//4.自定义输出路径
FileOutputFormat.setOutputPath(job, new Path(args[1]));
//job.setOutputFormatClass(TextOutputFormat.class);//对输出的数据格式化并写入磁盘 job.waitForCompletion(true);
}

由此,可以完成二次排序的完整代码如下:

 package Mapreduce;

 import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException; import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.io.WritableComparable;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat; public class SecondarySortTest {
public static void main(String[] args) throws Exception {
Job job = Job.getInstance(new Configuration(), SecondarySortTest.class.getSimpleName());
job.setJarByClass(SecondarySortTest.class);
//1.自定义输入路径
FileInputFormat.setInputPaths(job, new Path(args[0]));
//2.自定义mapper
//job.setInputFormatClass(TextInputFormat.class);
job.setMapperClass(MyMapper.class);
//job.setMapOutputKeyClass(Text.class);
//job.setMapOutputValueClass(TrafficWritable.class); //3.自定义reduce
job.setReducerClass(MyReducer.class);
job.setOutputKeyClass(TwoInt.class);
job.setOutputValueClass(NullWritable.class);
//4.自定义输出路径
FileOutputFormat.setOutputPath(job, new Path(args[1]));
//job.setOutputFormatClass(TextOutputFormat.class);//对输出的数据格式化并写入磁盘 job.waitForCompletion(true);
}
private static class MyMapper extends Mapper<LongWritable, Text, TwoInt, NullWritable>{
TwoInt K2 = new TwoInt();
@Override
protected void map(LongWritable key, Text value,
Mapper<LongWritable, Text, TwoInt, NullWritable>.Context context)
throws IOException, InterruptedException {
String[] splited = value.toString().split("\t");
K2.set(Integer.parseInt(splited[0]),Integer.parseInt(splited[1]));
context.write(K2, NullWritable.get());
}
}
//按照k2進行排序,分組,此數據分爲6組,在調用Reduce
private static class MyReducer extends Reducer<TwoInt, NullWritable, TwoInt, NullWritable>{
@Override
protected void reduce(TwoInt k2, Iterable<NullWritable> v2s,
Reducer<TwoInt, NullWritable, TwoInt, NullWritable>.Context context)
throws IOException, InterruptedException {
context.write(k2, NullWritable.get());
}
} private static class TwoInt implements WritableComparable<TwoInt>{
public int t1;
public int t2;
public void write(DataOutput out) throws IOException {
out.writeInt(t1);
out.writeInt(t2);
}
public void set(int t1, int t2) {
this.t1=t1;
this.t2=t2;
}
public void readFields(DataInput in) throws IOException {
this.t1=in.readInt();
this.t2=in.readInt();
}
public int compareTo(TwoInt o) {
if (this.t1 ==o.t1) { //當第一列相等的時候,第二列升序排列
return this.t2 -o.t2;
}
return this.t1-o.t1;//當第一列不相等的時候,按第一列升序排列
}
@Override
public String toString() {
return t1+"\t"+t2;
}
}
}

二次排序

第二部分:测试代码

(1)准备环境,准备测试数据

[root@neusoft-master filecontent]# vi twoint
3         3
3         2
3         1
2         2
2         1
1         1

(2)创建文件夹,并将文件上传到HDFS中

[root@neusoft-master filecontent]# hadoop dfs -mkdir /neusoft/

[root@neusoft-master filecontent]# hadoop dfs -put twoint /neusoft/

(3)执行jar包,查看中间过程

[root@neusoft-master filecontent]# hadoop jar SecondarySortTest.jar /neusoft/twoint  /out8

(4)查看结果

[root@neusoft-master filecontent]# hadoop dfs -ls /out8

[root@neusoft-master filecontent]# hadoop dfs -text /out8/part-r-00000

结果正确。

  • 如果输出有错误的话,或者输出不是数字(有时候是对象),需要查看是否重写了tostring()方法

 注意:如果需求变更为第一列的升序和第二列的降序,只需更改第3行

     public int compareTo(TwoInt o) {
if (this.t1 ==o.t1) { //當第一列相等的時候,第二列降序排列
return o.t2-this.t2;
} return this.t1-o.t1;//當第一列不相等的時候,按第一列升序排列 }

 总结:value不能参与排序,如果想参加排序需要放在key中,作为一个新的key进行排序。

MapReduce排序的更多相关文章

  1. Hadoop阅读笔记(三)——深入MapReduce排序和单表连接

    继上篇了解了使用MapReduce计算平均数以及去重后,我们再来一探MapReduce在排序以及单表关联上的处理方法.在MapReduce系列的第一篇就有说过,MapReduce不仅是一种分布式的计算 ...

  2. MapReduce排序输出

    hadoop的map是具有输出自动排序功能的~继续学习~ import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.c ...

  3. [大牛翻译系列]Hadoop(5)MapReduce 排序:次排序(Secondary sort)

    4.2 排序(SORT) 在MapReduce中,排序的目的有两个: MapReduce可以通过排序将Map输出的键分组.然后每组键调用一次reduce. 在某些需要排序的特定场景中,用户可以将作业( ...

  4. [大牛翻译系列]Hadoop(6)MapReduce 排序:总排序(Total order sorting)

    4.2.2 总排序(Total order sorting) 有的时候需要将作业的的所有输出进行总排序,使各个输出之间的结果是有序的.有以下实例: 如果要得到某个网站中最受欢迎的网址(URL),就需要 ...

  5. Mapreduce之排序&规约&实战案例

    MapReduce 排序和序列化 简单介绍 ①序列化 (Serialization) 是指把结构化对象转化为字节流②反序列化 (Deserialization) 是序列化的逆过程. 把字节流转为结构化 ...

  6. Hadoop (六):MapReduce基本使用

    MapReduce原理 背景 因为如果要对海量数据进行计算,计算机的内存可能会不够. 因此可以把海量数据切割成小块多次计算. 而分布式系统可以把小块分给多态机器并行计算. MapReduce概述 Ma ...

  7. Hadoop学习笔记—10.Shuffle过程那点事儿

    一.回顾Reduce阶段三大步骤 在第四篇博文<初识MapReduce>中,我们认识了MapReduce的八大步骤,其中在Reduce阶段总共三个步骤,如下图所示: 其中,Step2.1就 ...

  8. [大牛翻译系列]Hadoop 翻译文章索引

    原书章节 原书章节题目 翻译文章序号 翻译文章题目 链接 4.1 Joining Hadoop(1) MapReduce 连接:重分区连接(Repartition join) http://www.c ...

  9. Hadoop系列(三):hadoop基本测试

    下面是对hadoop的一些基本测试示例 Hadoop自带测试类简单使用 这个测试类名叫做 hadoop-mapreduce-client-jobclient.jar,位置在 hadoop/share/ ...

随机推荐

  1. MTK 预置apk

    一.如何将带源码的APK预置进系统? 1)     在 packages/apps 下面以需要预置的 APK的 名字创建一个新文件夹,以预置一个名为Test的APK 为例 2)     将 Test ...

  2. DB索引、索引覆盖、索引优化

    ###########索引########### @see   http://mp.weixin.qq.com/s/4W4iVOZHdMglk0F_Ikao7A 聚集索引(clustered inde ...

  3. HybridApp启动引导页的实现

    有一种帅叫做长话短说,@孙红雷,--这可以叫做“短帅”吗,^_^ 首先说下思路,既然是Hybrid APP, 那就是可以用html的方式实现,启动引导页比较常见的展示方式是滑动,那么我们就可以使用图片 ...

  4. python3.5 中Django框架连接mysql

    ps:mysqldb目前还不支持3.0python唉,最近赶了个新潮,用起了Python3.4跟Django1.6,数据库依然是互联网企业常见的MySql.悲催的是在Python2.7时代连接MySq ...

  5. Waf-Bypass-Learning

    WAF Bypass 综合篇: WAF攻防研究之四个层次Bypass WAF Bypass WAF Cookbook - MayIKissYou My Waf Bypass Series Articl ...

  6. zabbix设置报警通知

    邮件通知是最流行的报警通知方式,这里配置邮件通知 1. 配置通知邮箱信息(发件人)的邮箱信息 2. 填写信息 3. 事件(Action)通知配置 点击创建动作 添加一个触发条件 点击添加 添加一个操作 ...

  7. 【转】java文件操作大全

    一.获得控制台用户输入的信息 public String getInputMessage() throws IOException...{         System.out.println(&qu ...

  8. Android对touch事件的拦截,在View Tree上的传递顺序

    当发生touch事件时,系统会产生一个MotionEvent并且沿着View Tree开始传递.首先获取MotionEvent是View Tree的根节点,根节点通常是一个ViewGroup,View ...

  9. 详解SQL中的GROUP BY语句

    下面为您介绍SQL语句中GROUP BY 语句,GROUP BY 语句用于结合合计函数,根据一个或多个列对结果集进行分组. 希望对您学习SQL语句有所帮助. SQL GROUP BY 语法 SELEC ...

  10. Linux调试分析诊断利器——strace

    strace是个功能强大的Linux调试分析诊断工具,可用于跟踪程序执行时进程系统调用(system call)和所接收的信号,尤其是针对源码不可读或源码无法再编译的程序. 在Linux系统中,用户程 ...