Hadoop序列化和Java序列化的示例分析

46次阅读
没有评论

丸趣 TV 小编给大家分享一下 Hadoop 序列化和 Java 序列化的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!

Java 序列化机制将对象装换为连续的 byte 数据, 这些数据可以在以后还原 (反序列化) 成原来的对象
Java 中, 要想一个类的实例可被序列化, 该类须实现 Serializable 接口. Serializable 接口是一个标志, 没有任何方法, 其定义如下

 public interface Serializable { }

定义一个类 Block1, 该类实现了 Serializable 接口

 class Block1 implements Serializable {
 private int one = 1;
 private int two = 2;
 private int three = 3;
 @Override
 public String toString() { return  Block1 [one=  + one +  , two=  + two +  , three=  + three + ] 
 }
}

定义一个类 JavaSerializeTest, 测试 Java 序列化机制

 public class JavaSerializeTest { public static void main(String[] args) throws IOException, ClassNotFoundException { Block1 block = new Block1();
 ByteArrayOutputStream baos = null;
 ObjectOutputStream oos = null;
 ObjectInputStream ois = null;
 try {
 //  创建一个 ByteArrayOutputStream 对象 baos
 baos = new ByteArrayOutputStream();
 //  装饰 ByteArrayOutputStream 对象 baos,  得到 ObjectOutputStream 对象 oos
 oos = new ObjectOutputStream(baos);
 //  对 block 进行序列化,  序列化到 baos 中
 oos.writeObject(block);
 //  从字节数组输出流 baos 中得到字节数组
 byte[] bytes = baos.toByteArray();
 System.out.println(序列化 Block1 对象为 byte 数组, byte 数组长度为:  + bytes.length);
 //  以字节数组 bytes 创建 ByteArrayInputStream 对象,  再把这个对象装饰成 ObjectInputStream 对象 ois
 ois = new ObjectInputStream(new ByteArrayInputStream(bytes));
 //  调用 ObjectInputStream 对象 ois 的 readObject()方法,  实现反序列化,  返回一个 Block1 对象 block1
 Block1 block1 = (Block1) ois.readObject();
 System.out.println(byte 数组反序列化,  还原成 Block1 对象:   + block1);
 } finally {
 // 关闭流
 }
 }
}

Console 输出:
序列化 Block1 对象为 byte 数组, byte 数组长度: 72
byte 数组反序列化, 还原成 Block1 对象: Block1 [one=1, two=2, three=3]

ObjectOutputStream 提供了一些 writeX()方法, 包括 writeInt(), writeLong(), writeFloat(), writeUTF()…
JavaAPI:
public final void writeObject(Object obj) throws IOException
将指定的对象写入 ObjectOutputStream。对象的类、类的签名,以及类及其所有父类型的非瞬态和非静态字段的值都将被写入

由于 Java 的序列化机制太过强大, 可以看出只有 3 个属性 (都为 int 类型, 一共 12 个字节) 的 Block1 对象 block, 序列化后生成的字节数组却有 72 个字节, 因此对于 Hadoop 来说, 需要一个新的序列化机制

Hadoop 中, 要想一个类的实例可被序列化, 该类须实现 Writable 接口.
Writable 接口有两个方法, write()序列化和 readFields()反序列化, 其定义如下:

 public interface Writable {
 /*
 *  将对象(this)的属性字段序列化到输出流 DataOuput out 中。 */
 void write(DataOutput out) throws IOException;
 /*
 *  从输入流 DataInput in 中读取属性字段信息,重组为(this)对象,这是一个反序列化操作。 */
 void readFields(DataInput in) throws IOException;
}

定义一个类 Block2, 该类实现了 Writable 接口

 class Block2 implements Writable {
 private int one = 1;
 private int two = 2;
 private int three = 3;
 /*
 *  将对象(this)的属性字段序列化到输出流 DataOuput out 中。 */
 @Override
 public void write(DataOutput out) throws IOException { out.writeInt(one);
 out.writeInt(two);
 out.writeInt(three);
 }
 /*
 *  从输入流 DataInput in 中读取属性字段信息,重组为(this)对象,这是一个反序列化操作。 */
 @Override
 public void readFields(DataInput in) throws IOException { one = in.readInt();
 //  为了看出来反序列化效果,  交换第 two 和 three,
 three = in.readInt(); // two=3
 two = in.readInt(); // three=2
 }
 @Override
 public String toString() { return  Block2 [one=  + one +  , two=  + two +  , three=  + three + ] 
 }
}

PS: write()方法中 out.writeX(x)和 readFields()方法中 x = in.readX()顺序必须一致, 否则无法保证数据的正确性

定义一个类 HadoopSerializeTest, 测试 Hadoop 序列化机

 public class HadoopSerializeTest { public static void main(String[] args) throws IOException, ClassNotFoundException { Block2 block = new Block2();
 ByteArrayOutputStream baos = null;
 DataOutputStream dos = null;
 DataInputStream dis = null;
 try {
 //  创建一个 ByteArrayOutputStream 对象 baos
 baos = new ByteArrayOutputStream();
 //  装饰 ByteArrayOutputStream 对象 baos,  得到 DataOutputStream 对象 dos
 dos = new DataOutputStream(baos);
 //  对 block 进行序列化,  序列化到 baos 中
 block.write(dos);
 //  从 baos 中得到字节数组
 byte[] bytes = baos.toByteArray();
 System.out.println(序列化 Block2 对象为 byte 数组, byte 数组长度为:   + bytes.length);
 //  以字节数组 bytes 创建 ByteArrayInputStream 对象,  再把这个对象装饰成 DataInputStream 对象 dis
 dis = new DataInputStream(new ByteArrayInputStream(bytes));
 Block2 block1 = new Block2();
 System.out.println(未反序列化的 Block2 对象:   + block1);
 //  调用 block1 的 readFields(DataInput)方法,  实现反序列化,  交换 two 和 three 的值
 block1.readFields(dis);
 System.out.println(byte 数组反序列化,  还原成 Block2 对象:  + block1);
 } finally {
 // 关闭流
 }
 }
}

Console 输出:
序列化 Block2 对象为 byte 数组, byte 数组长度: 12
未反序列化的 Block2 对象: Block2 [one=1, two=2, three=3]
byte 数组反序列化, 还原成 Block2 对象: Block2 [one=1, two=3, three=2]

由于 Block2 对象 block 序列化时只输出 3 个 int, 序列化后生成的字节数组只有 12 个字节, 和 Java 的序列化机制的输出结果 (72 个字节) 对比, Hadoop 的序列化结果紧凑而快速

以上是“Hadoop 序列化和 Java 序列化的示例分析”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注丸趣 TV 行业资讯频道!