• 大数据框架hadoop的序列化机制


    Java内建序列化机制

    在Windows系统上序列化的Java对象,可以在UNIX系统上被重建出来,不需要担心不同机器上的数据表示方法,也不需要担心字节排列次序

    在Java中,使一个类的实例可被序列化非常简单,只需要在类声明中加入implements Serializable即可。Serializable接口是一个标志,不具有任何成员函数,其定义如下:

    public interface Serializable {

    }

    Block类通过声明它实现了Serializable 接口,立即可以获得Java提供的序列化功能。代码如下:

    public class Block implements Writable, Comparable<Block>, Serializable

    由于序列化主要应用在与I/O相关的一些操作上,其实现是通过一对输入/输出流来实现的。如果想对某个对象执行序列化动作,可以在某种OutputStream对象的基础上创建一个对象流ObjectOutputStream对象,然后调用writeObject()就可达到目的。

    下面是序列化对象的例子:

    Block block1=new Block(7806259420524417791L,39447755L,56736651L);

    ... ...

    ByteArrayOutputStream out = new ByteArrayOutputStream();

    ObjectOutputStream objOut = new ObjectOutputStream(out);

    objOut.writeObject(block1);

    但是,序列化以后的对象在尺寸上有点过于充实了,以Block类为例,它只包含3个长整数,但是它的序列化结果竟然有112字节。包含3个长整数Block对象的序列化结果如下:

    -84, -19, 0, 5, 115, 114, 0, 23, 111, 114, 103, 46, 115, 101, 97, 110, 100, 101, 110, 103, 46, 116, 101, 115, 116, 46, 66, 108, 111, 99, 107, 40, -7, 56, 46, 72, 64, -69, 45, 2, 0, 3, 74, 0, 7, 98, 108, 111, 99, 107, 73, 100, 74, 0, 16, 103, 101, 110, 101, 114, 97, 116, 105, 111, 110, 115, 83, 116, 97, 109, 112, 74, 0, 8, 110, 117, 109, 66, 121, 116, 101, 115, 120, 112, 108, 85, 103, -107, 104, -25, -110, -1, 0, 0, 0, 0, 3, 97, -69, -117, 0, 0, 0, 0, 2, 89, -20, -53


    Hadoop序列化机制

    和Java序列化机制不同(在对象流ObjectOutputStream对象上调用writeObject()方法),Hadoop的序列化机制通过调用对象的write()方法(它带有一个类型为DataOutput的参数),将对象序列化到流中。反序列化的过程也是类似,通过对象的readFields(),从流中读取数据。值得一提的是,Java序列化机制中,反序列化过程会不断地创建新的对象,但在Hadoop的序列化机制的反序列化过程中,用户可以复用对象,这减少了Java对象的分配和回收,提高了应用的效率。

    public static void main(String[] args) {

        try {

            Block block1 = new Block(1L,2L,3L);

            ... ...

            ByteArrayOutputStream bout = new ByteArrayOutputStream();

            DataOutputStream dout = new DataOutputStream();

            block1.write(dout);

            dout.close();

            ... ...

        }

        ... ...

    }

    由于Block对象序列化时只输出了3个长整数,block1的序列化结果一共有24字节。


    Hadoop Writable机制

    Hadoop引入org.apache.hadoop.io.Writable接口,作为所有可序列化对象必须实现的接口。

    和java.io.Serializable不同,Writable接口不是一个说明性接口,它包含两个方法:

    publicinterface Writable {

      /**

       * Serialize the fields of this object to <code>out</code>.

       * @param out <code>DataOuput</code> to serialize this object into.

       * @throws IOException

       */

      void write(DataOutput outthrows IOException;

      /**

       * Deserialize the fields of this object from <code>in</code>

       * For efficiency, implementations should attempt to re-use storage in the

       * existing object where possible.</p>

       * @param in <code>DataInput</code> to deseriablize this object from.

       * @throws IOException

       */

      void readFields(DataInput inthrows IOException;

    }

    Writable.write(DataOutput out)方法用于将对象写入二进制的DataOutput中,反序列化的过程由readFields(DataInput in)从DataInput流中读取状态完成。下面是一个例子:

    public class Block {

        private long blockId;

        private long numBytes;

        private long generationsStamp;

        public void write(DataOutput out) throws IOException {

            out.writeLong(blockId);

            out.writeLong(numBytes);

            out.writeLong(generationsStamp);

        }

        public void readFields(DataInput in) throws IOException {

            this.blockId = in.readLong();

            this.numBytes = in.readLong();

            this.generationsStamp = in.readLong();

            if (numBytes < 0 ) {

                throw new IOException("Unexpected block size:" + numBytes);

            }

        }

    }

    Hadoop序列化机制中还包括另外几个重要接口:WritableComparable、RawComparator和WritableComparator。

    Comparable是一个对象本身就已经支持自比较所需要实现的接口(如Integer自己就可以完成比较大小操作),实现Comparable接口的方法compareTo(),通过传入要比较的对象即可进行比较。

       而Comparator是一个专用的比较器,可以完成两个对象之间大小的比较。实现Comparator接口的compare()方法,通过传入需要比较的两个对象来实现对两个对象之间大小的比较。



    参考:

    DataOutput接口实现类有: - liango - 博客园

    http://www.cnblogs.com/liango/p/7122440.html



  • 相关阅读:
    C#后台去除字符串最后一个字符
    C#后台验证含0的正整数
    jQuery提交表单的几种方式
    C#后台获取当前时间并格式化
    获取EasyUI日期输入框的值
    jQuery将字符串转换为数字
    JQ和JS获取span标签的内容
    正则
    json 拖拽
    event事件对象
  • 原文地址:https://www.cnblogs.com/liango/p/7142306.html
Copyright © 2020-2023  润新知