对于null
键/值使用NullWritable
比使用null
文本(即new Text(null)
)有什么优势?我从«Hadoop:权威指南»一书中看到以下内容。
NullWritable
是Writable
的特殊类型,因为它具有零长度序列化。没有字节写入流或从流中读取。它被用作占位符;例如,在在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);
}
...
}