文档章节

Hadoop序列化&Java序列化

w
 wall--e
发布于 2016/04/13 19:39
字数 1113
阅读 64
收藏 1

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的序列化结果紧凑而快速

© 著作权归作者所有

w
粉丝 7
博文 31
码字总数 25016
作品 0
东城
程序员
私信 提问
加载中

评论(0)

Hadoop权威指南阅读笔记(三)

hadoop的序列化机制与java的序列化机制不同,他将对象序列化到流中,值得一提的是java的序列化机制是不断的创建对象,但在Hadoop的序列化机制中,用户可以服用对象这样就减少了java对象的分配...

蓝狐乐队
2014/04/27
120
0
Java拾遗:004 - JDK、Hadoop、Hessian序列化

JDK序列化 在分布式架构中,序列化是分布式的基础构成之一,我们需要把单台设备上的数据通过序列化(编码、压缩)后通过网络传输给网络中的其它设备,从而实现信息交换。JDK对Java中的对象序...

一别丶经年
2018/08/05
52
0
【hadoop】18.MapReduce-序列化

简介 序列化就是把内存中的对象,转换成字节序列(或其他数据传输协议)以便于存储(持久化)和网络传输。 反序列化就是将收到字节序列(或其他数据传输协议)或者是硬盘的持久化数据,转换成...

Areya
2019/01/12
72
0
hadoop2.2原理: 序列化浅析

序列化是指将一个对象编码成字节流,之后从字节流中重构对象; 为什么需要序列化? 答:用序列化接口可以将对象实例从存储到本地文件或者传送到网络的另一端的节点上; 序列化过程: 序列化的...

蓝狐乐队
2014/04/22
145
0
Hive 随谈(六)– Hive 的扩展特性

Hive 是一个很开放的系统,很多内容都支持用户定制,包括: 文件格式:Text File,Sequence File 内存中的数据格式: Java Integer/String, Hadoop IntWritable/Text 用户提供的 map/reduce...

红薯
2010/04/21
3.1K
1

没有更多内容

加载失败,请刷新页面

加载更多

maven插件加载类问题

https://www.cnblogs.com/coder-chi/p/11305498.html

Java搬砖工程师
34分钟前
32
0
(免费)霍兰德职业兴趣测试 在线测试霍兰德职业兴趣

霍兰德职业兴趣测试通过对你的个性进项测试评估,并为你关联到具体的职业。霍兰德职业兴趣量表是由美国著名的心理学教授霍兰德编制,具有广泛的应用和深度的职业兴趣理论。霍兰德职业兴趣量表...

蛤蟆丸子
35分钟前
74
0
在Linux中对pthread_create的未定义引用

我从https://computing.llnl.gov/tutorials/pthreads/在网络上获取了以下演示 #include <pthread.h>#include <stdio.h>#define NUM_THREADS 5void *PrintHello(void *threadid){ ......

javail
36分钟前
68
0
CAS原理分析及ABA问题详解

什么是CAS CAS即Compare And Swap的缩写,翻译成中文就是比较并交换,其作用是让CPU比较内存中某个值是否和预期的值相同,如果相同则将这个值更新为新值,不相同则不做更新,也就是CAS是原子...

Onegoleya
38分钟前
51
0
安卓版微信视频播放全屏处理

问题 在安卓版微信里,video在播放的时候,如果在没有做任何处理的情况下,微信会全屏播放你的视频,会严重影响一些例如直播之类的边看视频边交互的H5应用(注:在iOS里可以通过playsinline...

Jack088
48分钟前
61
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部