mapreduce编程(一)-二次排序

MapReduce-三次排序-曾经想不通的二次排序 上一篇博客说明了怎么自定义Key,而且用了二次排序的例子来做测试,但没有详细的说明二次排序,这一篇说详细的说明二次排序, 为了说明曾经一个思想的误区,特地做了一个3个字段的二次排序来说明。后面称其为“三次排序”。 测试数据: a1,b2,c5 a4,b1,c3 a1,b2,c4 a2,b2,c4 a2,b1,c4 a4,b1,c2 测试目的:输出以下结果首先根据第一个自段排序,如 阅读详情

转自:http://blog.youkuaiyun.com/heyutao007/article/details/5890103


mr自带的例子中的源码SecondarySort,我重新写了一下,基本没变。

这个例子中定义的map和reduce如下,关键是它对输入输出类型的定义:(java泛型编程) 

public static class Map extends Mapper<LongWritable, Text, IntPair, IntWritable> 
public static class Reduce extends Reducer<IntPair, NullWritable, IntWritable, IntWritable> 

1 首先说一下工作原理:

在map阶段,使用job.setInputFormatClass定义的InputFormat将输入的数据集分割成小数据块splites,同时InputFormat提供一个RecordReder的实现。本例子中使用的是TextInputFormat,他提供的RecordReder会将文本的一行的行号作为key,这一行的文本作为value。这就是自定义Map的输入是<LongWritable, Text>的原因。然后调用自定义Map的map方法,将一个个<LongWritable, Text>对输入给Map的map方法。注意输出应该符合自定义Map中定义的输出<IntPair, IntWritable>。最终是生成一个List<IntPair, IntWritable>。在map阶段的最后,会先调用job.setPartitionerClass对这个List进行分区,每个分区映射到一个reducer。每个分区内又调用job.setSortComparatorClass设置的key比较函数类排序。可以看到,这本身就是一个二次排序。如果没有通过job.setSortComparatorClass设置key比较函数类,则使用key的实现的compareTo方法。在第一个例子中,使用了IntPair实现的compareTo方法,而在下一个例子中,专门定义了key比较函数类。
在reduce阶段,reducer接收到所有映射到这个reducer的map输出后,也是会调用job.setSortComparatorClass设置的key比较函数类对所有数据对排序。然后开始构造一个key对应的value迭代器。这时就要用到分组,使用jobjob.setGroupingComparatorClass设置的分组函数类。只要这个比较器比较的两个key相同,他们就属于同一个组,它们的value放在一个value迭代器,而这个迭代器的key使用属于同一个组的所有key的第一个key。最后就是进入Reducer的reduce方法,reduce方法的输入是所有的(key和它的value迭代器)。同样注意输入与输出的类型必须与自定义的Reducer中声明的一致。 

2  二次排序就是首先按照第一字段排序,然后再对第一字段相同的行按照第二字段排序,注意不能破坏第一次排序的结果 。例如

输入文件
20 21
50 51
50 52
50 53
50 54
60 51
60 53
60 52
60 56
60 57
70 58
60 61
70 54
70 55
70 56
70 57
70 58
1 2
3 4
5 6
7 82
203 21
50 512
50 522
50 53
530 54
40 511
20 53
20 522
60 56
60 57
740 58
63 61
730 54
71 55
71 56
73 57
74 58
12 211
31 42
50 62
7 8
输出:(注意需要分割线)
------------------------------------------------
1       2
------------------------------------------------
3       4
------------------------------------------------
5       6
------------------------------------------------
7       8
7       82
------------------------------------------------
12      211
------------------------------------------------
20      21
20      53
20      522
------------------------------------------------
31      42
------------------------------------------------
40      511
------------------------------------------------
50      51
50      52
50      53
50      53
50      54
50      62
50      512
50      522
------------------------------------------------
60      51
60      52
60      53
60      56
60      56
60      57
60      57
60      61
------------------------------------------------
63      61
------------------------------------------------
70      54
70      55
70      56
70      57
70      58
70      58
------------------------------------------------
71      55
71      56
------------------------------------------------
73      57
------------------------------------------------
74      58
------------------------------------------------
203     21
------------------------------------------------
530     54
------------------------------------------------
730     54
------------------------------------------------
740     58 

3  具体步骤:
(1)自定义key

在mr中,所有的key是需要被比较和排序的,并且是二次,先根据partitione,再根据大小。而本例中也是要比较两次。先按照第一字段排序,然后再对第一字段相同的按照第二字段排序。根据这一点,我们可以构造一个复合类IntPair,他有两个字段,先利用分区对第一字段排序,再利用分区内的比较对第二字段排序。
所有自定义的key应该实现接口WritableComparable,因为是可序列的并且可比较的。并重载方法:

[cpp]  view plain copy
  1. //反序列化,从流中的二进制转换成IntPair  
  2. public void readFields(DataInput in) throws IOException          
  3. //序列化,将IntPair转化成使用流传送的二进制  
  4. public void write(DataOutput out)  
  5. //key的比较  
  6. public int compareTo(IntPair o)          
  7. //另外新定义的类应该重写的两个方法  
  8. //The hashCode() method is used by the HashPartitioner (the default partitioner in MapReduce)  
  9. public int hashCode()   
  10. public boolean equals(Object right)  

(2)由于key是自定义的,所以还需要自定义一下类:
(2.1)分区函数类。这是key的第一次比较。

[cpp]  view plain copy
  1. public static class FirstPartitioner extends Partitioner<IntPair,IntWritable>  

在job中使用setPartitionerClasss设置Partitioner。
(2.2)key比较函数类。这是key的第二次比较。这是一个比较器,需要继承WritableComparator。

[cpp]  view plain copy
  1. public static class KeyComparator extends WritableComparator  

必须有一个构造函数,并且重载 public int compare(WritableComparable w1, WritableComparable w2)

另一种方法是 实现接口RawComparator。
在job中使用setSortComparatorClass设置key比较函数类。
(2.3)分组函数类。在reduce阶段,构造一个key对应的value迭代器的时候,只要first相同就属于同一个组,放在一个value迭代器。这是一个比较器,需要继承WritableComparator。

[cpp]  view plain copy
  1. public static class GroupingComparator extends WritableComparator  

分组函数类也必须有一个构造函数,并且重载 public int compare(WritableComparable w1, WritableComparable w2)
分组函数类的另一种方法是实现接口RawComparator。
在job中使用setGroupingComparatorClass设置分组函数类。

另外注意的是,如果reduce的输入与输出不是同一种类型,则不要定义Combiner也使用reduce,因为Combiner的输出是reduce的输入。除非重新定义一个Combiner。 

3 代码。

这个例子中没有使用key比较函数类,而是使用key的实现的compareTo方法。 

[java]  view plain copy
  1. package secondarySort;  
  2. import java.io.DataInput;  
  3. import java.io.DataOutput;  
  4. import java.io.IOException;  
  5. import java.util.StringTokenizer;  
  6. import org.apache.hadoop.conf.Configuration;  
  7. import org.apache.hadoop.fs.Path;  
  8. import org.apache.hadoop.io.IntWritable;  
  9. import org.apache.hadoop.io.LongWritable;  
  10. import org.apache.hadoop.io.Text;  
  11. import org.apache.hadoop.io.WritableComparable;  
  12. import org.apache.hadoop.io.WritableComparator;  
  13. import org.apache.hadoop.mapreduce.Job;  
  14. import org.apache.hadoop.mapreduce.Mapper;  
  15. import org.apache.hadoop.mapreduce.Partitioner;  
  16. import org.apache.hadoop.mapreduce.Reducer;  
  17. import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;  
  18. import org.apache.hadoop.mapreduce.lib.input.TextInputFormat;  
  19. import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;  
  20. import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat;  
  21.   
  22. public class SecondarySort {  
  23.     //自己定义的key类应该实现WritableComparable接口  
  24.     public static class IntPair implements WritableComparable<IntPair> {  
  25.         int first;  
  26.         int second;  
  27.         /** 
  28.          * Set the left and right values. 
  29.          */  
  30.         public void set(int left, int right) {  
  31.             first = left;  
  32.             second = right;  
  33.         }  
  34.         public int getFirst() {  
  35.             return first;  
  36.         }  
  37.         public int getSecond() {  
  38.             return second;  
  39.         }  
  40.         @Override  
  41.         //反序列化,从流中的二进制转换成IntPair  
  42.         public void readFields(DataInput in) throws IOException {  
  43.             // TODO Auto-generated method stub  
  44.             first = in.readInt();  
  45.             second = in.readInt();  
  46.         }  
  47.         @Override  
  48.         //序列化,将IntPair转化成使用流传送的二进制  
  49.         public void write(DataOutput out) throws IOException {  
  50.             // TODO Auto-generated method stub  
  51.             out.writeInt(first);  
  52.             out.writeInt(second);  
  53.         }  
  54.         @Override  
  55.         //key的比较  
  56.         public int compareTo(IntPair o) {  
  57.             // TODO Auto-generated method stub  
  58.             if (first != o.first) {  
  59.                 return first < o.first ? -1 : 1;  
  60.             } else if (second != o.second) {  
  61.                 return second < o.second ? -1 : 1;  
  62.             } else {  
  63.                 return 0;  
  64.             }  
  65.         }  
  66.           
  67.         //新定义类应该重写的两个方法  
  68.         @Override  
  69.         //The hashCode() method is used by the HashPartitioner (the default partitioner in MapReduce)  
  70.         public int hashCode() {  
  71.             return first * 157 + second;  
  72.         }  
  73.         @Override  
  74.         public boolean equals(Object right) {  
  75.             if (right == null)  
  76.                 return false;  
  77.             if (this == right)  
  78.                 return true;  
  79.             if (right instanceof IntPair) {  
  80.                 IntPair r = (IntPair) right;  
  81.                 return r.first == first && r.second == second;  
  82.             } else {  
  83.                 return false;  
  84.             }  
  85.         }  
  86.     }  
  87.      /** 
  88.        * 分区函数类。根据first确定Partition。 
  89.        */  
  90.       public static class FirstPartitioner extends Partitioner<IntPair,IntWritable>{  
  91.         @Override  
  92.         public int getPartition(IntPair key, IntWritable value,   
  93.                                 int numPartitions) {  
  94.           return Math.abs(key.getFirst() * 127) % numPartitions;  
  95.         }  
  96.       }  
  97.         
  98.       /** 
  99.        * 分组函数类。只要first相同就属于同一个组。 
  100.        */  
  101.     /*//第一种方法,实现接口RawComparator 
  102.     public static class GroupingComparator implements RawComparator<IntPair> { 
  103.         @Override 
  104.         public int compare(IntPair o1, IntPair o2) { 
  105.             int l = o1.getFirst(); 
  106.             int r = o2.getFirst(); 
  107.             return l == r ? 0 : (l < r ? -1 : 1); 
  108.         } 
  109.         @Override 
  110.         //一个字节一个字节的比,直到找到一个不相同的字节,然后比这个字节的大小作为两个字节流的大小比较结果。 
  111.         public int compare(byte[] b1, int s1, int l1, byte[] b2, int s2, int l2){ 
  112.             // TODO Auto-generated method stub 
  113.              return WritableComparator.compareBytes(b1, s1, Integer.SIZE/8,  
  114.                      b2, s2, Integer.SIZE/8); 
  115.         } 
  116.     }*/  
  117.     //第二种方法,继承WritableComparator  
  118.     public static class GroupingComparator extends WritableComparator {  
  119.           protected GroupingComparator() {  
  120.             super(IntPair.class, true);  
  121.           }  
  122.           @Override  
  123.           //Compare two WritableComparables.  
  124.           public int compare(WritableComparable w1, WritableComparable w2) {  
  125.             IntPair ip1 = (IntPair) w1;  
  126.             IntPair ip2 = (IntPair) w2;  
  127.             int l = ip1.getFirst();  
  128.             int r = ip2.getFirst();  
  129.             return l == r ? 0 : (l < r ? -1 : 1);  
  130.           }  
  131.         }  
  132.       
  133.           
  134.     // 自定义map  
  135.     public static class Map extends  
  136.             Mapper<LongWritable, Text, IntPair, IntWritable> {  
  137.         private final IntPair intkey = new IntPair();  
  138.         private final IntWritable intvalue = new IntWritable();  
  139.         public void map(LongWritable key, Text value, Context context)  
  140.                 throws IOException, InterruptedException {  
  141.             String line = value.toString();  
  142.             StringTokenizer tokenizer = new StringTokenizer(line);  
  143.             int left = 0;  
  144.             int right = 0;  
  145.             if (tokenizer.hasMoreTokens()) {  
  146.                 left = Integer.parseInt(tokenizer.nextToken());  
  147.                 if (tokenizer.hasMoreTokens())  
  148.                     right = Integer.parseInt(tokenizer.nextToken());  
  149.                 intkey.set(left, right);  
  150.                 intvalue.set(right);  
  151.                 context.write(intkey, intvalue);  
  152.             }  
  153.         }  
  154.     }  
  155.     // 自定义reduce  
  156.     //  
  157.     public static class Reduce extends  
  158.             Reducer<IntPair, IntWritable, Text, IntWritable> {  
  159.         private final Text left = new Text();  
  160.         private static final Text SEPARATOR =   
  161.               new Text("------------------------------------------------");  
  162.         public void reduce(IntPair key, Iterable<IntWritable> values,  
  163.                 Context context) throws IOException, InterruptedException {  
  164.             context.write(SEPARATOR, null);  
  165.             left.set(Integer.toString(key.getFirst()));  
  166.             for (IntWritable val : values) {  
  167.                 context.write(left, val);  
  168.             }  
  169.         }  
  170.     }  
  171.     /** 
  172.      * @param args 
  173.      */  
  174.     public static void main(String[] args) throws IOException, InterruptedException, ClassNotFoundException {  
  175.         // TODO Auto-generated method stub  
  176.         // 读取hadoop配置  
  177.         Configuration conf = new Configuration();  
  178.         // 实例化一道作业  
  179.         Job job = new Job(conf, "secondarysort");  
  180.         job.setJarByClass(SecondarySort.class);  
  181.         // Mapper类型  
  182.         job.setMapperClass(Map.class);  
  183.         // 不再需要Combiner类型,因为Combiner的输出类型<Text, IntWritable>对Reduce的输入类型<IntPair, IntWritable>不适用  
  184.         //job.setCombinerClass(Reduce.class);  
  185.         // Reducer类型  
  186.         job.setReducerClass(Reduce.class);  
  187.         // 分区函数  
  188.         job.setPartitionerClass(FirstPartitioner.class);  
  189.         // 分组函数  
  190.         job.setGroupingComparatorClass(GroupingComparator.class);  
  191.           
  192.         // map 输出Key的类型  
  193.         job.setMapOutputKeyClass(IntPair.class);  
  194.         // map输出Value的类型  
  195.         job.setMapOutputValueClass(IntWritable.class);  
  196.         // rduce输出Key的类型,是Text,因为使用的OutputFormatClass是TextOutputFormat  
  197.         job.setOutputKeyClass(Text.class);  
  198.         // rduce输出Value的类型  
  199.         job.setOutputValueClass(IntWritable.class);  
  200.           
  201.         // 将输入的数据集分割成小数据块splites,同时提供一个RecordReder的实现。  
  202.         job.setInputFormatClass(TextInputFormat.class);  
  203.         // 提供一个RecordWriter的实现,负责数据输出。  
  204.         job.setOutputFormatClass(TextOutputFormat.class);  
  205.           
  206.         // 输入hdfs路径  
  207.         FileInputFormat.setInputPaths(job, new Path(args[0]));  
  208.         // 输出hdfs路径  
  209.         FileOutputFormat.setOutputPath(job, new Path(args[1]));  
  210.         // 提交job  
  211.         System.exit(job.waitForCompletion(true) ? 0 : 1);  
  212.     }  
  213. }  


Mapreduce二次排序实例 Mapreduce可以简单的分为三个阶段:map阶段、shuffle阶段、reduce阶段。shuffle阶段包括分区、分组两个步骤,二次排序发生在分区步骤。 分区:通过分区函数将满足条件的分在同一个区(第一次排序)。同一个区的数据然后再排序(第二次排序)。分区是对key进行操作。 分组:将相同key值的value整合成一个集合() 实例:有一张phone表,包含mac、time 阅读详情

相关推荐

多路输出电源的交叉调整率:从理论到无源优化实践

本文深入探讨了多路输出电源中的交叉调整率问题,分析了其物理根源及无源优化方法。通过漏感与耦合的理论分析,结合加权反馈、电感耦合等五种无源优化技术,帮助工程师有效解决交叉调整率挑战。文章还以TDK-Lambda CUT75系列为例,展示了优化技术的实际应用与效果。

weixin_26886855的博客 280

二次排序

1 原理     二次排序就是首先按照第一字段排序,然后再对第一字段相同的行按照第二字段排序,注意不能破坏第一次排序的结果。     这里主要讲如何使用一个Mapreduce就可以实现二次排序。Hadoop有自带的SecondarySort程序,但这个程序只能对整数进行排序,所以我们需要对其进行改进,使其可以对任意字符串进行排序。下面会分别列出这两个程序的详解。       

奋斗吧_-小青年 1297

RK3568(buildroot)利用squashfs+overlay实现嵌入式系统高可靠存储方案

本文详细介绍了在RK3568嵌入式平台上,基于Buildroot系统,利用squashfs只读根文件系统与overlayfs可写层相结合的高可靠存储方案。该方案能有效防止设备意外断电导致的系统文件损坏,通过内核配置、启动脚本编写及镜像制作,实现系统核心的只读保护与用户数据的持久化分离,显著提升嵌入式设备的现场稳定性。

weixin_29189381的博客 548

Hadoop-SecondarySort

MapReduce框架对处理结果的输出会根据key值进行默认的排序,这个默认排序可以满足一部分需求。为了满足复杂的需求需要Hadoop二次排序Secondary Sort。 过程 在map阶段,使用job.setInputFormatClass定义的InputFormat将输入的数据集分割成小数据块splites,同时InputFormat提供一个RecordReder的实现。 他提供的

忧郁王子的专栏 709

从零开始:手把手教你做转录组与代谢组的联合分析(含R代码)

本文详细介绍了转录组与代谢组联合分析的全流程,包括数据准备、预处理、差异分析及可视化方法,并提供了实用的R代码示例。通过多组学整合分析,研究者可以更全面地理解生物过程,适用于疾病机制和药物开发等医学研究领域。

weixin_29306317的博客 438

SBP依赖计算中的蝴蝶效应:一个Prefab修改如何触发全量重建?

本文深入探讨了Unity中SBP(Scriptable Build Pipeline)依赖计算的蝴蝶效应,解析了Prefab修改如何触发全量重建的机制。通过分析Asset与Object的层级关系、依赖计算的三种维度及CacheEntry系统,揭示了全量重建的根本原因,并提供了依赖可视化工具开发、优化策略与最佳实践,帮助开发者提升构建效率。

weixin_29015051的博客 444

MapReduce

1、定义 MapReduce 是google提出的一个软件架构,用于大规模数据集的并行计算。当前的软件实现是指定一个Map(映射)函数,用来把一组键值对映射成一组新的键值对,指定并发的Reduce(归纳)函数,用来保证所有映射的键值对中的每一个共享相同的键值【维基百科】。 2、例子【单词个数统计】 1.1 输入一段文本 1.2 任务分发给每个节点 1.3 节点对各自收到的文本进行

ziliangxiao的专栏 373

YOLOv13优化Faster_Block:卷积(Partial Convolution)、多层感知机(MLP)结构和残差连接

Faster_Block 代表了现代深度学习中效率与性能平衡的一个典型案例。它通过部分卷积技术巧妙地减少了计算开销,同时通过精心设计的架构保持了强大的特征学习能力。这种设计思想对于移动端部署、实时应用和大规模模型训练都具有重要意义。 未来的发展方向可能包括更智能的动态分割策略、与新兴硬件的深度适配,以及与其他先进技术(如自注意力机制、神经架构搜索等)的结合。Faster_Block 的成功展示了在深度学习领域,创新往往来自于对问题本质的深刻理解和巧妙的工程实现。

FJN110的博客 427

hadoop-mapreduce2-原理

运行原理源码hadoop-2.6.0-cdh5.7.0-src

program哲学 621

Unity零基础到入门 ☀️| 【UI系统学习】认识Unity引擎中几种最常用 UI系统,这一篇文章就够用了!

轻松学会 Unity 的 UGUI基础控件 使用 Unity中的UI介绍 UI即User Interface(用户界面)的简称。泛指用户的操作界面,UI设计主要指界面的样式,美观程度。而使用上,对软件的人机交互、操作逻辑、界面美观的整体设计则是同样重要的另一个门道。好的UI不仅是让软件变得有个性有品味,还要让软件的操作变得舒适、简单、自由,充分体现软件的定位和特点。 据我所知Unity中有两种自带的UI,一种是UGUI,一种是GUI Legacy GUI:旧版 UI,只有两个组件:文字和图片,配合鼠标事件来

努力前行,总会成为自己心中的那道光 2万+

鱼鹰优化算法(OOA)详解:从猛禽捕食智能到优化算法实现

鱼鹰优化算法(Osprey Optimization Algorithm, OOA)是2023年提出的一种新型元启发式优化算法,灵感来源于鱼鹰(一种中型猛禽)高效的捕食策略。算法模拟了鱼鹰从空中识别水下鱼类位置并俯冲捕食,然后将捕获的鱼带至安全位置享用的全过程,以此抽象出全局探索和局部开发两个核心阶段。OOA算法具有参数少、结构简单、收敛速度快、全局寻优能力强等特点。自提出以来,已在函数优化、机器学习参数调优(如CatBoost模型)、路径规划等多个领域展现出良好性能,为解决复杂优化问题提供了新的有效工具。

qq_42212808的博客 273

mapreduce二次排序详解

mapreduce二次排序详解 - linzch3 - 博客园 什么是二次排序 待排序的数据具有多个字段,首先对第一个字段排序,再对第一字段相同的行按照第二字段排序,第二次排序不破坏第一次排序的结果,这个过程就称为二次排序。 如何在mapreduce中实现二次排序 mapreduce的工作原理 MR的工作原理如下图(如果看不清可右键新标签页查看): 图片部分数据参考自:Hadoop — MapReduce原理解析 相关重点: 分区(partitioning):使得具有相同Key值的键值.

hellojoy的博客 2742

YOLO26改进策略【小目标改进】| 添加专用于小目标的检测层 附YOLOv1~YOLOv11的检测头变化详解

在目标检测领域,小目标检测一直是一个具有挑战性的问题。算法以其高效快速的特点受到广泛关注,然而在面对小目标时,仍存在一些局限性。本文将介绍如何在中添加小目标检测层,以提高对小目标的检测能力。原始模型结构如下: 二、有效特征层对应的检测头类别 2.1 P3/8 - small检测头 原始模型中的对应的检测头主要用于检测相对较小的目标。其特征图大小相对较大,空间分辨率较高。 适合检测尺寸大概在到像素左右的目标。 2.2 P4/16 - medium检测头 这个检测头对应的经过了更多的下采样操作,相比P3/

Limiiiing的博客 351

MapReduce实现二次排序

默认情况下,Map输出的结果会按照key进行排序,但在实际的应用中,有时间我们不仅要对key进行排序,同时还要对value进行排序,这时候就要用到mapreduce中的二次排序。 一、 二次排序原理分析 我们对二次排序分为以下几个阶段: (1)Map起始阶段 在Map阶段,通过job.setInputFormatClass()定义的InputFormat,将输入的数据集切分成小的split,同时InputFormat提供一个RecordRead...

YF_Li123的博客 1682

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

MapReduce的二次排序

MapReduce的二次排序 二次排序的需求说明    在mapreduce操作时,shuffle阶段会多次根据key值排序。但是在shuffle分组后,相同key值的values序列的顺序是不确定的(如下图)。如果想要此时value值也是排序好的,这种需求就是二次排序。                                      ...

雪泪寒的博客 2327

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

MapReduce二次排序

默认情况下,Map输出的结果会对Key进行默认的排序,但是有时候需要对Key排序的同时还需要对Value进行排序,这时候就要用到二次排序了。下面我们来说说二次排序 1、二次排序原理 我们把二次排序分为以下几个阶段 Map起始阶段 在Map阶段,使用job.setInputFormatClass()定义的InputFormat,将输入的数据集分割成小数据块spl...

913

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

MapReduce排序机制深度解密:从默认排序到二次排序

Override// 自定义排序规则:按年龄升序,年龄相同按薪水降序= o.age) {// 年龄升序// 年龄相同:按薪水降序// 注意顺序@Override@Override@Override// 先按名字排序= 0) {// 名字相同按年龄// 在作业中设置强制排序:MapReduce框架自动对所有中间数据排序两阶段排序:Map端快速排序 + Reduce端归并排序默认规则:Key的compareTo方法定义的自然顺序。

✨ 欢迎来到【Seal ^_^ 的优快云博客】!✨ 1893

MapReduce排序之 二次排序

一:背景 Hadoop中虽然有自动排序和分组,由于自带的排序是按照Key进行排序的,有些时候,我们希望同时对Key和Value进行排序。自带的排序功能就无法满足我们了,还好Hadoop提供了一些组件可以让开发人员进行二次排序。 二:技术实现 我们先来看案例需求 #需求1: 首先按照第一列数字升序排列,当第一列数字相同时,第二列数字也升序排列(列之间用制表符\t隔开) 3 3 3

lavimer 2086

MapReduce实现二次排序(九)

文章目录1. 前言2. 需求分析3. 二次排序的实现原理4. 上传文件5. 代码实现6. 效果截图 1. 前言 默认情况下, Map会对key自动进行排序,但是有时候需要对key排序的同时还需要对value进行排序,这就是所谓的二次排序。 2. 需求分析 假设现在有如下数据:每行两列,列与列之间的分隔符是制表符(”\t“),输出的结果先按照第一个字段的升序排列,如果第一列的值相等,在按照第二个...

RivenDong 1614

mapreduce二次排序

一、二次排序发生在需要对 Key 排序的同时再对 Value 进行排序的情况下。 主要分为以下几个阶段: Map 起始阶段 在Map阶段,使用 job.setInputFormatClass() 定义的 InputFormat ,将输入的数据集分割成小数据块 split,同时 InputFormat 提供一个 RecordReader的实现。本课程中使用的是 TextInputFormat,

ZoeYen_ 695
上一篇: MapReduce初级案例(转自虾皮博客)
下一篇: mapreduce编程(二)- 大象书中求每一年的最高温度
码上富贵
博客等级 码龄17年 1万+粉丝 135原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值