mapreduce设置setMapOutputKeyClass与setMapOutputValueClass原因

一般的mapreduce的wordcount程序如下:

public class WcMapper extends Mapper<LongWritable, Text, Text, LongWritable> {

    @Override
    protected void map(LongWritable key, Text value, Context ctx) throws IOException, InterruptedException {

        String[] words = value.toString().split(" ");
        for (int i = 0; i < words.length; i++) {
            ctx.write(new Text(words[i]), new LongWritable(1L));
        }
    }
}

 

public class WcReduer extends Reducer<Text, LongWritable, Text, LongWritable> {

    LongWritable count = new LongWritable();
    @Override
    protected void reduce(Text key, Iterable<LongWritable> values, Context ctx) throws IOException, InterruptedException {
        Iterator<LongWritable> itr = values.iterator();
        long sum = 0L;
        while (itr.hasNext()) {
            sum = sum + itr.next().get();
        }
        count.set(sum);
        ctx.write(key, count);
    }
}

  

驱动作业代码:

public class JobClient {

    public static void main(String[] args) throws Exception {

        Job job = Job.getInstance();
        job.setJarByClass(JobClient.class);
        job.setMapperClass(WcMapper.class);
        job.setReducerClass(WcReduer.class);

        job.setInputFormatClass(TextInputFormat.class);
        job.setOutputFormatClass(TextOutputFormat.class);

        job.setJobName("wordcount");
        FileInputFormat.addInputPath(job, new Path("/daxin/hadoop-mapreduce/words"));
        FileOutputFormat.setOutputPath(job, new Path("/daxin/hadoop-mapreduce/wordcount-result"));
        job.waitForCompletion(true);
    }
}

  

提交作业会报错:

Error: java.io.IOException: Type mismatch in key from map: expected org.apache.hadoop.io.LongWritable, received org.apache.hadoop.io.Text
	at org.apache.hadoop.mapred.MapTask$MapOutputBuffer.collect(MapTask.java:1072)
	at org.apache.hadoop.mapred.MapTask$NewOutputCollector.write(MapTask.java:715)
	at org.apache.hadoop.mapreduce.task.TaskInputOutputContextImpl.write(TaskInputOutputContextImpl.java:89)
	at org.apache.hadoop.mapreduce.lib.map.WrappedMapper$Context.write(WrappedMapper.java:112)
	at com.daxin.blog.WcMapper.map(WcMapper.java:20)
	at com.daxin.blog.WcMapper.map(WcMapper.java:13)
	at org.apache.hadoop.mapreduce.Mapper.run(Mapper.java:146)
	at org.apache.hadoop.mapred.MapTask.runNewMapper(MapTask.java:787)
	at org.apache.hadoop.mapred.MapTask.run(MapTask.java:341)
	at org.apache.hadoop.mapred.YarnChild$2.run(YarnChild.java:164)
	at java.security.AccessController.doPrivileged(Native Method)
	at javax.security.auth.Subject.doAs(Subject.java:422)
	at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1657)
	at org.apache.hadoop.mapred.YarnChild.main(YarnChild.java:158) 

通过异常信息我们可以定位错误在源码中的位置:org.apache.hadoop.mapred.MapTask.MapOutputBuffer#collect,具体关键源码如下:

 public synchronized void collect(K key, V value, final int partition
                                     ) throws IOException {
      reporter.progress();
      if (key.getClass() != keyClass) {
        throw new IOException("Type mismatch in key from map: expected "
                              + keyClass.getName() + ", received "
                              + key.getClass().getName());
      }
      if (value.getClass() != valClass) {
        throw new IOException("Type mismatch in value from map: expected "
                              + valClass.getName() + ", received "
                              + value.getClass().getName());
      }
   .....
}

此处key.getClass可以确定是Text,需要确定keyClass是什么类型。下面就将确定一下keyClass类型,可以发现keyClass赋值源码:

 keyClass = (Class<K>)job.getMapOutputKeyClass();

 getMapOutputKeyClass源码:

  public Class<?> getMapOutputKeyClass() {
    Class<?> retv = getClass(JobContext.MAP_OUTPUT_KEY_CLASS, null, Object.class);
    if (retv == null) {
      retv = getOutputKeyClass();
    }
    return retv;
  } 

其中MAP_OUTPUT_KEY_CLASS则是获取map输出的key的类型,由于我们驱动代码没有设置因此此处得到的值为默认值null,接下在调用getOutputKeyClass方法:

  public Class<?> getOutputKeyClass() {
    return getClass(JobContext.OUTPUT_KEY_CLASS,
                    LongWritable.class, Object.class);
  }

 

 public static final String OUTPUT_KEY_CLASS = "mapreduce.job.output.key.class";

  

通过获取OUTPUT_KEY_CLASS的类型,OUTPUT_KEY_CLASS表示的是作业的key的输出类型,但是由于我们没有设置因此获取默认值为LongWritable。但是实际上我们的MapTask输出的key为Text,因而报如上类型不匹配错误。同理Map的value也有类似问题。为了解决此问题就需要显式的设置MapTask的Key、Value输出类型。代码如下:

        job.setMapOutputKeyClass(Text.class);
        job.setMapOutputValueClass(LongWritable.class);

 

原文地址:https://www.cnblogs.com/leodaxin/p/8831092.html

时间: 2024-11-05 18:34:00

mapreduce设置setMapOutputKeyClass与setMapOutputValueClass原因的相关文章

关于C# Winform DataGridView 设置DefaultCellStyle无效的原因与解决方案

上周在开发Winform 项目中,我曾遇到一个看似简单,但一直都没有解决的问题,那就是:设置winform DataGridView控件的行DefaultCellStyle,但却没有任何变化,我也曾求助于博问:http://q.cnblogs.com/q/72294/,但大家给的答案没有一个能解决这个问题,可能是问题重现不太容易,我自己也曾多次在其它项目中尝试重现这个问题,但一直都是正确的,没有出现我当前项目的问题,简直要崩溃啊! 先来看看我原有的代码: private void Form1_L

MapReduce设置输出文件到多个文件夹下

一:自定义OutputFormat类MapReduce默认的OutPutFormat会将结果输出文件放置到一个我们指定的目录下,但如果想把输出文件根据某个条件,把满足不同条件的内容分别输出到不同的目录下, 就需要自定义实现OutputFormat类,且重写RecordWriter方法.在驱动类中设置job.setOutputFormatClass方法为自定义实现的OutputFormat类 下面案例是一组购物文本数据,将其中的好评和差评分别输出到对应的好评文件夹下.差评文件夹下. 二:自定义实现

xml文件的根节点layout_width或者layout_height设置无效果的原因分析

在android开发中相信大家对ListView.GridView等组建都很熟悉,在使用它们的时候需要自己配置相关的Adapter,并且配置现骨干的xml文件作为ListView等组建的子View,这些xml文件在Adapter的getView方法中调用.例如: public View getView(int position, View convertView, ViewGroup parent) { if(convertView==null) { convertView = App.getL

Mapreduce设置多路径输入输出

最近写Mapreduce程序时,想用到多路径输入,一次输入多个文件夹下的数据.并且希望输出路径也可以区分,修改输出文件的名称.查了相关资料,已实现. 多路径输入 设置Mapreduce的输入是HDFS上多个文件夹下的数据,在main函数下稍作配置即可,示例代码如下: public static void main(String[] args) throws Exception { String ioPath[] = { "hdfs://10.1.2.3:8020/user/me/input/fo

重新绑定ItemsSource先设置ItemsSource = null;的原因

即报错信息为:在使用 ItemsSource 之前,项集合必须为空. 原因:Items和ItemSource,只能有一个生效,想用其中一个,另一个必须是空. 重新绑定ItemSource,虽然绑定的集合对象Clear了,但是items还没有清空:然后再次绑定就会有问题. 所以要么设置ItemSource =null :要么 Items.Clear();

(转)mysql 无法设置外键的原因总结

在Mysql中创建外键时,经常会遇到问题而失败,这是因为Mysql中还有很多细节需要我们去留意,我自己总结并查阅资料后列出了以下几种常见原因. 1.  两个字段的类型或者大小不严格匹配.例如,如果一个是int(10),那么外键也必须设置成int(10),而不是int(11),也不能是tinyint.另外,你还必须确定两个字段是否一个为 signed,而另一个又是unsigned(即:无符号),这两字段必须严格地一致匹配,更多关于signed和unsigned的信息,请参阅:http://www.

PHPStorm+XDebug进行调试图文教程以及解析wamp的php.ini设置不生效的原因

这篇文章主要为大家详细介绍了PHPStorm+XDebug进行调试图文教程,内容很丰富,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 笔者的开发环境如下:Windows8.1+Apache+PhpStorm+XDebug+Firefox(XDebug helper 1.4.3插件). 一.XDebug安装配置 (1)下载XDebug下载地址:http://www.xdebug.org/必须下载跟机器上安装的php匹配的版本才行.具体下载方法如下:将phpinfo网页的源代码拷贝到http:/

UIView设置阴影无效的原因之一

本想在底部的按钮设置个阴影, 代码如下: self.layer.shadowColor = [UIColor blackColor].CGColor; self.layer.shadowOffset = CGSizeMake(-5, 5); self.layer.shadowOpacity = 0.8; self.layer.shadowRadius = 10; 写完后,死活不出效果,那个纠结啊,明明代码没问题啊 最后发现,按钮没有设置背景色,把背景色设置后,就好!

微信小程序首页index.js获取不到app.js中动态设置的globalData的原因以及解决方法

前段时间开发了一款微信小程序,运行了也几个月了,在index.js中的onLoad生命周期里获取app.js中onLaunch生命周期中在接口里动态设置的globalData一直没有问题,结果昨天就获取不到动态设置的global数据了.因为我要获取小程序的unionid以及通过unionid去获取微信的openId,并且共享数据,最开始我是通过storage来做数据共享的,后来测试发现storage存在莫名被清空的情况,后来转用globalData来做数据共享,查了下,是因为app.js中的on