重新认识mapreduce
写这篇文章,是因为最近遇到了mapreduce的二次排序问题。以前的理解不完全正确。首先看一下mapreduce的过程

相信这张图熟悉MR的人都应该见过,再来一张图

wordcount也不细说了,hadoop里面的hello,world

之前我的理解是map过来的<k,v>会形成(k,<v1,v2,v3...>)的格式,并且按照这种思路写出来不少的mapreduce程序,而且没有错。
后来自定义Writable对象,封装一组值作为key,也没有什么问题,而且一直认为key只要在compareTo中重写 了方法就万事大吉,而且compareTo返回0的会作为相同的key。误区就在这里,之前一直认为key相同的value会合并到一个"list"中-。这句话就有错,key是key,value是value,根本不会将key对应的value合并在一起,真实情况是默认将key相同(compareTo返回0的)的合并成了一组,在组相同的里面去foreach里面的value,如果是自定义key的话你可以将key打印一下,或发现key并不相同。
上代码:
public class Entry implements WritableComparable<Entry> {
private String yearMonth;
private int count;
public Entry() {
}
@Override
public int compareTo(Entry entry) {
int result = this.yearMonth.compareTo(entry.getYearMonth());
if (result == 0) {
result = Integer.compare(count, entry.getCount());
}
return result;
}
@Override
public void write(DataOutput dataOutput) throws IOException {
dataOutput.writeUTF(yearMonth);
dataOutput.writeInt(count);
}
@Override
public void readFields(DataInput dataInput) throws IOException {
this.yearMonth = dataInput.readUTF();
this.count = dataInput.readInt();
}
public String getYearMonth() {
return yearMonth;
}
public void setYearMonth(String yearMonth) {
this.yearMonth = yearMonth;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
@Override
public String toString() {
return yearMonth;
}
}
自定义分区 EntryPartitioner.java
public class EntryPartitioner extends Partitioner<Entry, Text> {
@Override
public int getPartition(Entry entry, Text paramVALUE, int numberPartitions) {
return Math.abs((entry.getYearMonth().hashCode() % numberPartitions));
}
}
自定义分组
public class EntryGroupingComparator extends WritableComparator {
public EntryGroupingComparator() {
super(Entry.class, true);
}
@Override
public int compare(WritableComparable a, WritableComparable b) {
Entry a1 = (Entry) a;
Entry b1 = (Entry) b;
return a1.getYearMonth().compareTo(b1.getYearMonth());
}
}
mapper类
public class SecondarySortMapper extends
Mapper<LongWritable, Text, Entry, Text> { private Entry entry = new Entry();
private Text value = new Text(); @Override
protected void map(LongWritable key, Text lines, Context context)
throws IOException, InterruptedException {
String line = lines.toString();
String[] tokens = line.split(",");
String yearMonth = tokens[0] + "-" + tokens[1];
int count = Integer.parseInt(tokens[2]); entry.setYearMonth(yearMonth);
entry.setCount(count);
value.set(tokens[2]);
context.write(entry, value); }
}
reducer类
public class SecondarySortReducer extends Reducer<Entry, Text, Entry, Text> {
@Override
protected void reduce(Entry key, Iterable<Text> values, Context context)
throws IOException, InterruptedException {
System.out.println("-----------------华丽的分割线-----------------");
StringBuilder builder = new StringBuilder();
for (Text value : values) {
System.out.println(key+"==>"+value);
builder.append(value.toString());
builder.append(",");
}
context.write(key, new Text(builder.toString()));
}
}
reducer中打印出来的跟原来想的不一样,一组的值除了自定义分组的属性相同外,其他的属性有不同的。看来以前是自己理解不够深入啊,特此写出,以示警戒
重新认识mapreduce的更多相关文章
- Mapreduce的文件和hbase共同输入
Mapreduce的文件和hbase共同输入 package duogemap; import java.io.IOException; import org.apache.hadoop.co ...
- mapreduce多文件输出的两方法
mapreduce多文件输出的两方法 package duogemap; import java.io.IOException; import org.apache.hadoop.conf ...
- mapreduce中一个map多个输入路径
package duogemap; import java.io.IOException; import java.util.ArrayList; import java.util.List; imp ...
- Hadoop 中利用 mapreduce 读写 mysql 数据
Hadoop 中利用 mapreduce 读写 mysql 数据 有时候我们在项目中会遇到输入结果集很大,但是输出结果很小,比如一些 pv.uv 数据,然后为了实时查询的需求,或者一些 OLAP ...
- [Hadoop in Action] 第5章 高阶MapReduce
链接多个MapReduce作业 执行多个数据集的联结 生成Bloom filter 1.链接MapReduce作业 [顺序链接MapReduce作业] mapreduce-1 | mapr ...
- MapReduce
2016-12-21 16:53:49 mapred-default.xml mapreduce.input.fileinputformat.split.minsize 0 The minimum ...
- 使用mapreduce计算环比的实例
最近做了一个小的mapreduce程序,主要目的是计算环比值最高的前5名,本来打算使用spark计算,可是本人目前spark还只是简单看了下,因此就先改用mapreduce计算了,今天和大家分享下这个 ...
- MapReduce剖析笔记之八: Map输出数据的处理类MapOutputBuffer分析
在上一节我们分析了Child子进程启动,处理Map.Reduce任务的主要过程,但对于一些细节没有分析,这一节主要对MapOutputBuffer这个关键类进行分析. MapOutputBuffer顾 ...
- MapReduce剖析笔记之七:Child子进程处理Map和Reduce任务的主要流程
在上一节我们分析了TaskTracker如何对JobTracker分配过来的任务进行初始化,并创建各类JVM启动所需的信息,最终创建JVM的整个过程,本节我们继续来看,JVM启动后,执行的是Child ...
- MapReduce剖析笔记之六:TaskTracker初始化任务并启动JVM过程
在上面一节我们分析了JobTracker调用JobQueueTaskScheduler进行任务分配,JobQueueTaskScheduler又调用JobInProgress按照一定顺序查找任务的流程 ...
随机推荐
- 框架SpringMVC笔记系列 一 基础
主题:SpringMVC 学习资料参考网址: 1.http://www.icoolxue.com 2.http://aokunsang.iteye.com/blog/1279322 1.SpringM ...
- Spark集群 + Akka + Kafka + Scala 开发(2) : 开发一个Spark应用
前言 在Spark集群 + Akka + Kafka + Scala 开发(1) : 配置开发环境,我们已经部署好了一个Spark的开发环境. 本文的目标是写一个Spark应用,并可以在集群中测试. ...
- Selenium学习笔记之外部化相关测试数据---xml
我们也可以用xml来定义一个信息更为丰富的UIMap.xml文件,比如,额外还添加控件所属的页,控件的类型,然后解析构建一个XMLParser类来读取相应的值. <?xml version=&q ...
- 网上图书商城3--Book模块
小技巧一:分页 ①PageBean<Book> findByCriteria(List<Expression> exprList, int pc) --- 通用的查询方法(p ...
- java.io.StreamCorruptedException: invalid type code: AC错误的解决方法
问题描述: 在向一个文件写入可序列化对象时,每次只想向文件的末尾添加一个可序列化的对象,于是使用了FileOutputStream(文件名,true)间接的构建了ObjectOutputStream流 ...
- this指向问题
我今天下午本来想做个就是tr鼠标移出之后过三秒把对应的input添加hiddens类 然后我就这样写了 $('.table>tbody>tr').mouseout(function(){ ...
- Sortable – 简单灵活的 JavaScript 拖放排序插件
当需要在网站中添加拖放排序功能的时候,jQuery UI 的排序组件可能是最流行的解决方案.今天给大家介绍另一款简单灵活的 JavaScript 拖放排序插件——Sortable,它使用 HTML5 ...
- JS中数组去除重复
法一:返回新数组每个位子类型没变 function outRepeat(a){ var hash=[],arr=[]; for (var i = 0; i < a.length; i++) { ...
- Ext.store.load callback
var paramsReceivable = {}; paramsReceivable.querytext = Ext.getCmp('hiddquerytext').g ...
- 定制Eclipse IDE之杂症篇
上文回顾:定制Eclipse IDE之插件篇(二) 该篇将讲述在开发Eclipse 插件过程发生的疑难杂症.不谈功能,只说病症. 前言.拿哪个Eclipse作为定制的基础? 我建议是你用哪个Eclip ...