写这篇文章,是因为最近遇到了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的更多相关文章

  1. Mapreduce的文件和hbase共同输入

    Mapreduce的文件和hbase共同输入 package duogemap;   import java.io.IOException;   import org.apache.hadoop.co ...

  2. mapreduce多文件输出的两方法

    mapreduce多文件输出的两方法   package duogemap;   import java.io.IOException;   import org.apache.hadoop.conf ...

  3. mapreduce中一个map多个输入路径

    package duogemap; import java.io.IOException; import java.util.ArrayList; import java.util.List; imp ...

  4. Hadoop 中利用 mapreduce 读写 mysql 数据

    Hadoop 中利用 mapreduce 读写 mysql 数据   有时候我们在项目中会遇到输入结果集很大,但是输出结果很小,比如一些 pv.uv 数据,然后为了实时查询的需求,或者一些 OLAP ...

  5. [Hadoop in Action] 第5章 高阶MapReduce

    链接多个MapReduce作业 执行多个数据集的联结 生成Bloom filter   1.链接MapReduce作业   [顺序链接MapReduce作业]   mapreduce-1 | mapr ...

  6. MapReduce

    2016-12-21  16:53:49 mapred-default.xml mapreduce.input.fileinputformat.split.minsize 0 The minimum ...

  7. 使用mapreduce计算环比的实例

    最近做了一个小的mapreduce程序,主要目的是计算环比值最高的前5名,本来打算使用spark计算,可是本人目前spark还只是简单看了下,因此就先改用mapreduce计算了,今天和大家分享下这个 ...

  8. MapReduce剖析笔记之八: Map输出数据的处理类MapOutputBuffer分析

    在上一节我们分析了Child子进程启动,处理Map.Reduce任务的主要过程,但对于一些细节没有分析,这一节主要对MapOutputBuffer这个关键类进行分析. MapOutputBuffer顾 ...

  9. MapReduce剖析笔记之七:Child子进程处理Map和Reduce任务的主要流程

    在上一节我们分析了TaskTracker如何对JobTracker分配过来的任务进行初始化,并创建各类JVM启动所需的信息,最终创建JVM的整个过程,本节我们继续来看,JVM启动后,执行的是Child ...

  10. MapReduce剖析笔记之六:TaskTracker初始化任务并启动JVM过程

    在上面一节我们分析了JobTracker调用JobQueueTaskScheduler进行任务分配,JobQueueTaskScheduler又调用JobInProgress按照一定顺序查找任务的流程 ...

随机推荐

  1. Oracle的建立表格

    找到table右键点击,选择新建: 输入名称,用拼音或者英文,中文容易出现错误.输入完名称选择列: 列也写好名称,类型可以选择,VARCHAR2()是字符串类型,括号里面写数字代表长度,英文字母和数字 ...

  2. HDU 4293---Groups(区间DP)

    题目链接 http://acm.split.hdu.edu.cn/showproblem.php?pid=4293 Problem Description After the regional con ...

  3. python django 多级业务树形结构规划及页面渲染

    概述: 在项目中,父级到子级结构并不少见,如果仅仅的两层树形结构,我们可以使用数据库的外键设计轻松做到,子级业务表设计一字段外键到父级业务表,这样子到父.父到子的查询都非常简单. 但是往往父子结构会有 ...

  4. Git远程和分支管理

    一.远程       Git是分布式版本控制系统,最重要的优点就是远程仓库托管代码.不用自己搭建一个服务器,在github上面注册一个账户就可免费获取远程仓库.      首先需要先在github上面 ...

  5. cnodejs社区论坛4--话题列表

  6. 04Mybatis_搭建Mybatis的开发环境

    第一步:导jia包: 1.导入Mybatis的核心jia包:

  7. json 对象 数组

    一.json写法以及获得其数据的方法 var jsons={ name:'wen', age:12, price:'qq' } console.log(typeof jsons);//object c ...

  8. zDialog 可拖拽弹出层

    zDialog弹出框: 代替window.open.window.alert.window.confirm:提供良好的用户体验: 水晶质感,设计细腻,外观漂亮: 兼容ie6/7/8.firefox2/ ...

  9. Infinite Scroll - jQuery & WP 无限滚动插件

    无限滚动(Infinite Scroll)也称为自动分页.滚动分页和无限分页.常用在图片.文章或其它列表形式的网页中,用来在滚动网页的时候自动加载下一页的内容.Infinite Scroll  这款  ...

  10. Zend Studio 中导出 PHP 语法颜色配置

    Zend Studio 中,虽然可以自行配置 PHP 语法颜色,但是,没有导出配置的按钮.介个,总不能每次都配置一次吧,那不是累死伦家啦?有图有真相: 强迫症患者总是无法停止折腾,虽然内心总有个声音不 ...