千家信息网

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

发表于:2024-11-29 作者:千家信息网编辑
千家信息网最后更新 2024年11月29日,小编给大家分享一下Hadoop序列化和Java序列化的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!Java序列化
千家信息网最后更新 2024年11月29日Hadoop序列化和Java序列化的示例分析

小编给大家分享一下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序列化的示例分析"这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注行业资讯频道!

0