使用ArrayWritable的序列化似乎以一种有趣的方式工作

时间:2011-10-27 16:16:04

标签: java hadoop mapreduce

我正在使用ArrayWritable,在某些时候我需要检查Hadoop如何序列化ArrayWritable,这是我通过设置job.setNumReduceTasks(0)得到的:

0    IntArrayWritable@10f11b8
3    IntArrayWritable@544ec1
6    IntArrayWritable@fe748f
8    IntArrayWritable@1968e23
11    IntArrayWritable@14da8f4
14    IntArrayWritable@18f6235

这是我正在使用的测试映射器:

public static class MyMapper extends Mapper<LongWritable, Text, LongWritable, IntArrayWritable> {

    public void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
        int red = Integer.parseInt(value.toString());
        IntWritable[] a = new IntWritable[100];

        for (int i =0;i<a.length;i++){
            a[i] = new IntWritable(red+i);
        }

        IntArrayWritable aw = new IntArrayWritable();
        aw.set(a);
        context.write(key, aw);
    }
}

IntArrayWritable取自javadoc中给出的示例:ArrayWritable

import org.apache.hadoop.io.ArrayWritable;
import org.apache.hadoop.io.IntWritable;

public class IntArrayWritable extends ArrayWritable {
    public IntArrayWritable() {
        super(IntWritable.class);
    }
}

我实际上检查了Hadoop的源代码,这对我没有意义。 ArrayWritable不应序列化类名,并且无法使用6/7十六进制值序列化100 IntWritable的数组。应用程序实际上似乎工作正常,reducer反序列化正确的值... 怎么了?我错过了什么?

4 个答案:

答案 0 :(得分:6)

您必须覆盖默认的toString()方法。

TextOutputFormat调用它来创建一个人类可读的格式。

尝试以下代码并查看结果:

public class IntArrayWritable extends ArrayWritable {
    public IntArrayWritable() {
        super(IntWritable.class);
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        for (String s : super.toStrings())
        {
            sb.append(s).append(" ");
        }
        return sb.toString();
    }
}

答案 1 :(得分:4)

问题是您从MapReduce作业获得的输出不是该数据的序列化版本。它被翻译成漂亮的印刷字符串。

当你将reducer的数量设置为零时,你的映射器现在会通过输出格式传递,这将格式化你的数据,可能会将其转换为可读的字符串。 它不会将其序列化,就好像它会被减速器拾取一样。

答案 2 :(得分:3)

您是否查看了SequenceFileInputFormat和SequenceFileOutputFormat?你可以用以下方式设置:

job.setInputFormatClass(SequenceFileInputFormat.class); 

job.setOutputFormatClass(TextOutputFormat.class);

答案 3 :(得分:0)

这很简单。 Hadoop使用thé方法write(DataOutput out)以序列化版本编写对象(有关更多信息,请参阅hadoop ArrayWritable doc)。当您通过IntArrayWritable扩展ArrayWritable时,您自己的类将使用继承类中的这些方法。 再见。