28

与使用文本(即)相比,NullWritable使用null键/值有什么优势。我从《Hadoop:权威指南》一书中看到以下内容。nullnew Text(null)

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

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

谢谢,

文卡特

4

3 回答 3

23

键/值类型必须在运行时给出,因此任何写入或读取NullWritables的内容都会提前知道它将处理该类型;文件中没有标记或任何内容。从技术上讲,NullWritables它们是“读取”的,只是“读取” aNullWritable实际上是无操作的。您可以亲眼看到根本没有任何书面或阅读内容:

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.

于 2013-04-24T18:42:11.607 回答
0

我改变了运行方法。和成功

@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;
}
于 2014-12-01T11:24:16.693 回答
0

您始终可以将字符串包装在您自己的 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);
    }
    ...
}
于 2016-07-27T09:20:06.657 回答