关于MapReduce框架中Key-Value对象的重用

原创 2016年08月30日 21:58:18
  • 问题说明

在写MapReduce的reduce程序时,有时会用到Java中Treemap容器对准备输出的

treeMap.put(new LongWritable(count), key);//有意调换K,V以便排序

但是输出时却发现key的值都是一个,而且都是最后一个put进入treeMap中的值!这是为什么?
请教了公司大牛wanglei2才知道其中的原因,在此感谢王老师并表达膜拜之情!
原因是Key-Value对象的重用导致的:Key是一个引用,它在栈中,指向堆中一个对象,同样Value也是如此。虽然reduce方法会反复执行多次,但key和value相关的对象只有两个,key和value的引用也是只有两个,reduce会反复重用这两个对象。所以上面代码段put进去的key指向的对象只有一个,对象的值为最后一个put进去的值,所以输出的key的值都为最后一个,而new LongWritable(count)是创建了一个新的对象。所以是不同的。所以如果要保存key或者value的结果,只能将其中的值取出另存或者重新clone一个对象(例如Text text= new Text(value) 或者 String a = value.toString()),而不能直接赋引用。因为引用从始至终都是指向同一个对象,你如果直接保存它们,那最后它们都指向最后一个输入记录。会影响最终计算结果而出错。

  • 程序验证:
package cn.bjut.vlsi.TreeMap;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;

import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;

public class TreeMapTest {

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO 自动生成的方法存根
        TreeMap<LongWritable,Text> treemap = new TreeMap<LongWritable, Text>();
        String[] cityName = {"北京","南京","秦皇岛","济南","天津","上海","苏州"};
        int i = 0;
        Text key = new Text();
        for(String str : cityName){
            key.set(str);
            i++;
            treemap.put(new LongWritable(i), key);
        }       
        System.out.println("******************TreeMap Output******************");   
        Set<Entry<LongWritable,Text>> entrySet = treemap.entrySet();
        for(Entry<LongWritable,Text> ent : entrySet){
            System.out.println(ent.getValue() + " " + ent.getKey());        
        }
    }
}
程序输出:

苏州 1
苏州 2
苏州 3
苏州 4
苏州 5
苏州 6
苏州 7

创建put中key的对象,程序改为:

package cn.bjut.vlsi.TreeMap;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;

import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;

public class TreeMapTest {

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO 自动生成的方法存根
        TreeMap<LongWritable,String > treemap = new TreeMap<LongWritable, String >();//*****修改****//
        String[] cityName = {"北京","南京","秦皇岛","济南","天津","上海","苏州"};
        int i = 0;
        Text key = new Text();
        for(String str : cityName){
            key.set(str);
            i++;
            treemap.put(new LongWritable(i), key.toString());//*****修改****//
        }       
        System.out.println("******************TreeMap Output******************");   
        Set<Entry<LongWritable,String >> entrySet = treemap.entrySet();//*****修改****//
        for(Entry<LongWritable,String > ent : entrySet){
            System.out.println(ent.getValue() + " " + ent.getKey());        
        }
    }
}

程序输出:

北京 1
南京 2
秦皇岛 3
济南 4
天津 5
上海 6
苏州 7

版权声明:本文为博主原创文章,未经博主允许不得转载。

java 对象转换为Map key-value形式

package com.newsoft.datacpl.util;import java.lang.reflect.Field; import java.lang.reflect.Method; im...
  • u012151597
  • u012151597
  • 2017年03月29日 14:37
  • 1741

Python+Hadoop Streaming实现MapReduce(如何给map和reduce的脚本传递参数)

1. 上一篇我们提到用python 和 hadoop streaming的方式写mapreduce,那么我们怎么向map和reduce的脚本传递参数呢,本来着重讲这个 2. 我们知道用java写ma...
  • JThink_
  • JThink_
  • 2015年01月15日 19:53
  • 5268

Hadoop 键值对的mapreduce过程剖析

Hadoop的Mapreduce是一个分布并行处理大数据的程序框架,一个Map/Reduce 作业(job) 通常会把输入的数据集切分为若干独立的数据块,由 map任务(task)以完全并行的方式处理...
  • xubcing
  • xubcing
  • 2012年08月04日 16:13
  • 2966

mapreduce 自定义key/value 输出分隔符

mapreduce 默认情况下 key/value 分隔符为:“\t” 测试的输出如下: 我们可以在代码中进行设置来自定义 key/value 输出分隔符:在代码中添加如下一行代码...
  • LIHUINIHAO
  • LIHUINIHAO
  • 2013年12月27日 10:53
  • 3444

MapReduce框架中Key-Value对象的重用

从代码看问题@Override protected void reduce(Text key, Iterable values,Context context) ...
  • fxdaniel
  • fxdaniel
  • 2015年12月24日 14:50
  • 987

用通俗易懂的大白话讲解Map/Reduce原理

Hadoop简介 Hadoop就是一个实现了Google云计算系统的开源系统,包括并行计算模型Map/Reduce,分布式文件系统HDFS,以及分布式数据库Hbase,同时Hadoop的相关项目...
  • lifuxiangcaohui
  • lifuxiangcaohui
  • 2014年03月31日 16:20
  • 139323

Mapreduce中map方法自定义key类

为map方法的key构造一个复合类public static class IntPair implements WritableComparable { int first; ...
  • GYQJN
  • GYQJN
  • 2016年01月25日 13:19
  • 1452

自定义实现Mapreduce计算的key类型

1. 在进行mapreduce编程时key键往往用于分组或排序,当我们在进行这些操作时Hadoop内置的key键数据类型不能满足需求时, 或针对用例优化自定义数据类型可能执行的更好。因此可以通过实现o...
  • u014432433
  • u014432433
  • 2016年04月09日 11:55
  • 2494

<hadoop>在hadoop集群的map和reduce函数中传递自定义对象

在hadoop集群中传递自定义对象
  • huahai_nb
  • huahai_nb
  • 2017年02月18日 15:29
  • 782

Mapreduce中Combiner的使用及误区

问题提出: 众所周知,Hadoop框架使用Mapper将数据处理成一个键值对,再网络节点间对其进行整理(shuffle),然后使用Reducer处理数据并进行最终输出。    在上述过程中,我们看到...
  • guoery
  • guoery
  • 2013年01月22日 11:18
  • 18734
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:关于MapReduce框架中Key-Value对象的重用
举报原因:
原因补充:

(最多只允许输入30个字)