在Hadoop中使用NullWritable的优点



对于null键/值使用NullWritable比使用null文本(即new Text(null))有什么优势?我从«Hadoop:权威指南»一书中看到以下内容。

NullWritableWritable的特殊类型,因为它具有零长度序列化。没有字节写入流或从流中读取。它被用作占位符;例如,在在MapReduce中,键或值可以在不需要的时候声明为NullWritable要使用该位置-它有效地存储了一个常量空值。NullWritable也可以当您想要存储值列表时,作为SequenceFile中的键是有用的到键值对。它是一个不可变的单例:实例可以通过调用NullWritable.get()

我不清楚如何使用NullWritable写出输出?是否会在开始的输出文件中有一个常量值,表明该文件的键或值是null,以便MapReduce框架可以忽略读取null键/值(以null为例)?此外,null文本实际上是如何序列化的?

谢谢,

Venkat

键/值类型必须在运行时给出,因此任何写入或读取NullWritables的操作都将提前知道它将处理该类型;文件里没有标记什么的。从技术上讲,NullWritables是"读取"的,只是"读取"NullWritable实际上是一个无操作。你可以自己看到,没有任何内容写入或读取:

NullWritable nw = NullWritable.get();
ByteArrayOutputStream out = new ByteArrayOutputStream();
nw.write(new DataOutputStream(out));
System.out.println(Arrays.toString(out.toByteArray())); // prints "[]"
ByteArrayInputStream in = new ByteArrayInputStream(new byte[0]);
nw.readFields(new DataInputStream(in)); // works just fine

至于你关于new Text(null)的问题,你可以再试一下:

Text text = new Text((String)null);
ByteArrayOutputStream out = new ByteArrayOutputStream();
text.write(new DataOutputStream(out)); // throws NullPointerException
System.out.println(Arrays.toString(out.toByteArray()));

Text将不工作与null String

我改变了run方法。和成功

@Override
public int run(String[] strings) throws Exception {
    Configuration config = HBaseConfiguration.create();  
    //set job name
    Job job = new Job(config, "Import from file ");
    job.setJarByClass(LogRun.class);
    //set map class
    job.setMapperClass(LogMapper.class);
    //set output format and output table name
    //job.setOutputFormatClass(TableOutputFormat.class);
    //job.getConfiguration().set(TableOutputFormat.OUTPUT_TABLE, "crm_data");
    //job.setOutputKeyClass(ImmutableBytesWritable.class);
    //job.setOutputValueClass(Put.class);
    TableMapReduceUtil.initTableReducerJob("crm_data", null, job);
    job.setNumReduceTasks(0);
    TableMapReduceUtil.addDependencyJars(job);
    FileInputFormat.addInputPath(job, new Path(strings[0]));
    int ret = job.waitForCompletion(true) ? 0 : 1;
    return ret;
}

你可以在你自己的Writable类中包装你的字符串,并使用一个布尔值来指示它是否为空字符串:

@Override
public void readFields(DataInput in) throws IOException { 
    ...
    boolean hasWord = in.readBoolean();
    if( hasWord ) {
        word = in.readUTF();
    }
    ...
}

@Override
public void write(DataOutput out) throws IOException {
    ...
    boolean hasWord = StringUtils.isNotBlank(word);
    out.writeBoolean(hasWord);
    if(hasWord) {
        out.writeUTF(word);
    }
    ...
}

相关内容

  • 没有找到相关文章

最新更新