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

  • 问题说明

在写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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值