在Hadoop中向DataOutput写入null

4
我正在使用Hadoop 0.20.2。我正在编写一个实现Writable接口的对象X。 X有几个字段是Integer的实例。对于这些字段,null值具有特殊意义。 在将对象序列化时,在Writable接口的write方法中向DataOutput out写入时,是否有一种方法可以写入null?还是应该使用单独的布尔值来表示该值为null?

你尝试过直接写入“null”吗?你能分享一下你重写的“write”方法吗? - Amar
尝试编写一个测试,其中您使用 null 值构造一个 X 对象,将其序列化、反序列化并确认值是否符合预期。如果这样可以正常工作,那么它应该也可以在 Hadoop 下正常工作。 - Chris Gerken
3个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
6

布尔值是将对象属性标记为NULL的标准过程。

考虑以下情况:

public class LongMessage implements Writable {

  private long tag;
  private String data;
  // interface methods omitted first
}

因为某些原因,data可能为null。我将按以下方式实现读/写:

  @Override
  public void readFields(DataInput in) throws IOException {
    tag = in.readLong();
    if (in.readBoolean()) {
      data = in.readUTF();
    } else {
      data = null;
    }
  }

  @Override
  public void write(DataOutput out) throws IOException {
    out.writeLong(tag);
    if (data != null) {
      out.writeBoolean(true);
      out.writeUTF(data);
    } else {
      out.writeBoolean(false);
    }
  }

即使这段代码比较易读,但需要注意的是,根据JavaDocs中#writeBoolean的说明,每个记录的常量开销为一字节:

将布尔值写入此输出流。如果参数v为true,则写入值(byte)1;如果v为false,则写入值(byte)0。


我不确定,但如果我记得正确的话,Hadoop会重用Writable实例,这意味着如果你从DataInput中读取到一个布尔值false,你应该将数据设置回默认值。否则,你可能会得到另一次运行的值。 - whiskeysierra
1
@whiskeysierra 没错。添加了一个 else 语句,将数据设置为 null。 - Thomas Jungblut

1
NullWritable是一种特殊的Writable类型,它具有零长度序列化。在流中不写入或读取任何字节。更多信息请参考Hadoop权威指南第104页。

0

在进行串行化时,Java对象序列化协议中,一个null对象的大小恰好为1字节。因此,在您自定义的Writablewrite方法中,我认为您不会遇到任何问题。

一般来说,这确实取决于您要建模的内容。如果您要表示一个Boolean,而null表示不存在,那么您应该将其默认为false。如果是整数,则应将其默认为数据集的默认值。所以,除非特定的"特殊意义"与之相关联,否则我认为您可以写入一个null,否则您应该使用一个默认值。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,