全网整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:400-708-3566

深入浅析Java Object Serialization与 Hadoop 序列化

一,Java Object Serialization

1,什么是序列化(Serialization)

序列化是指将结构化对象转化为字节流以便在网络上传输或者写到磁盘永久存储的过程。反序列化指将字节流转回结构化对象的逆过程。简单的理解就是对象转换为字节流用来传输和保存,字节流转换为对象将对象恢复成原来的状态。

2,序列化(Serialization)的作用

(1)一种持久化机制,把的内存中的对象状态保存到一个文件中或者数据库。

(2)一种通信机制,用套接字在网络上传送对象。

(3)Java远程方法调用(RMI)需要调用对象时,

3,实现了Serializable接口的对象的序列化

在java.io包中,接口Serialization用来作为实现对象串行化的工具 ,只有实现了Serialization的类的对象才可以被序列化。 Serializable接口中没有任何的方法,当一个类声明要实现Serializable接口时,只是表明该类参加序列化协议,而不需要实现任何特殊的方法。

要序列化一个对象,首先要创建OutputStream对象,然后将其封装在一个ObjectOutputStream对象内。此时,调用writeObject()方法将对象序列化并发送给OutputStream。在反序列化时,需要将一个InputStream封装在ObjectInputStream内,然后调用readObject(),得到的结果是一个Object对象,需要进行转型得到最后所需的对象。需要注意的是,在对一个Serializable对象进行反序列化的过程中,没有调用任何构造器,包括缺省的构造器,整个对象都是通过从InputStream中取得数据恢复过来的。对象序列化是面向字节的,因此采用InputStream和OutputStream层次结构。

对Student序列化

package cn.test.serializable;
/**
 * 序列化对象实现Serializable接口
 * @author Young
 * created on 2017-5-25
 */
import java.io.Serializable;
public class Student implements Serializable {
  private String id;
  private String name;
  public Student (String id,String name){
    this.id=id;
    this.name=name;
  }
  public String getId() {
    return id;
  }
  public void setId(String id) {
    this.id = id;
  }
  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
}

序列化

package cn.test.serializable;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
/**
 * 序列化
 * @author Young
 * created on 2017-5-25
 */
public class TestSerializable {
  public static void main(String[] args) {
    // TODO Auto-generated method stub
    Student stu=new Student("201441413110","yang");
    try {
      FileOutputStream out=new FileOutputStream("d:\\student");//创建OutputStream对象
      ObjectOutputStream ob=new ObjectOutputStream(out);//封装在一个ObjectOutputStream对象内
      ob.writeObject(stu);//调用writeObject()方法将对象序列化并发送给OutputStream,保存在d:\\student中
      ob.close();
      out.close();
    } catch (FileNotFoundException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }
}

反序列化

package cn.test.serializable;
/**
 * 反序列化
 * @author Young
 * created on 2017-5-25
 */
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream;
public class TestDeserializable {
  public static void main(String[] args) {
    // TODO Auto-generated method stub
    FileInputStream in;
    Student stu;
    try {
      in = new FileInputStream("d:\\student");
      ObjectInputStream ob=new ObjectInputStream(in);//InputStream封装在ObjectInputStream内
      stu=(Student) ob.readObject();//调用readObject(),得到的结果是一个Object对象,需要进行转型得到最后所需的对象.
      ob.close();
      in.close();
      System.out.println(stu.getId());
      System.out.println(stu.getName());
    } catch (FileNotFoundException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (ClassNotFoundException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }
}

序列化机制写到流中的数据有

1,声明和标记,比如声明使用了序列化协议、序列化协议版本、声明这是一个新的对象、声明这里开始一个新Class、结束标记等。

2,对象所属的类 ,类的长度,

3,SerialVersionUID, 序列化ID,如果没有指定,则会由算法随机生成一个8byte的ID。

4,所有的非transient和非static的属性的个数以及名称。名称长度,属性的值。

这只是简单对象序列化后写到流中的数据。如果是复杂对象序列化就会包含更多的信息。比如引用其他对象作为成员变量,这是会将引用的对象也进行序列化。还有序列化时,只对对象的状态进行保存,而不管对象的方法;当一个父类实现序列化,子类自动实现序列化,不需要显式实现Serializable接口;当一个对象的实例变量引用其他对象,序列化该对象时也把引用对象进行序列化。

二,Hadoop 序列化

hadoop在节点间的内部通讯使用的是RPC,RPC协议把消息翻译成二进制字节流发送到远程节点,远程节点再通过反序列化把二进制流转成原始的信息。

Hadoop使用自己的序列化格式Writable,它绝对紧凑、高速,但不太容易用Java以外的语言进行拓展和使用。

1,Writable接口

Writable接口定义了两个方法:一个将其状态写到DataOutput二进制流,另一个从DataInput二进制流读取其状态:

实现代码

package Hadoop.writable;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Writable;
/**
 * hadoop 序列化与反序列化
 * @author Young
 * created by 2017-6-9
 */
public class Serialize {
  public static byte[] serialize(Writable writable) throws IOException{
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    DataOutputStream dataout = new DataOutputStream(out);
    try {
      writable.write(dataout);
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }finally{
      dataout.close();
    }
    return out.toByteArray();
  }
  public static byte[] deserialize(Writable writable ,byte[] bytes) throws IOException{
    ByteArrayInputStream in = new ByteArrayInputStream(bytes);
    DataInputStream datain = new DataInputStream(in);
    try {
      writable.readFields(datain);
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    finally{
      datain.close();
    }
    return bytes;
  }
  public static void main(String[] args) throws IOException {
    // TODO Auto-generated method stub
    IntWritable intwritable = new IntWritable(20);
    IntWritable newwriatble =new IntWritable();
    byte[] bytes=Serialize.serialize(intwritable);
    deserialize(newwriatble,bytes);
    System.out.println(newwriatble.get());
  }
}

2,Hadoop序列化机制中还包含另外几个重要的接口:WritableComparable、RawComparator 和 WritableComparator

WritableComparable提供类型比较的能力,继承自Writable接口和Comparable接口,其中Comparable进行 类型比较。ByteWritable、IntWritable、DoubleWritable等java基本类型对应的Writable类型,都继承自 WritableComparable。

WritableComparable接口

package org.apache.hadoop.io;
import org.apache.hadoop.classification.InterfaceAudience.Public;
import org.apache.hadoop.classification.InterfaceStability.Stable;
import org.apache.hadoop.io.Writable;
@Public
@Stable
public interface WritableComparable<T> extends Writable, Comparable<T> {
}

对于MapReduce来说,类型的比较非常重要,因为中间有个基于键的排序阶段。Hadoop提供了一个具有高效比较能力的RawComparator接口。

RawComparator接口

package org.apache.hadoop.io;
import java.util.Comparator;
import org.apache.hadoop.classification.InterfaceAudience.Public;
import org.apache.hadoop.classification.InterfaceStability.Stable;
@Public
@Stable
public interface RawComparator<T> extends Comparator<T> {
  int compare(byte[] arg0, int arg1, int arg2, byte[] arg3, int arg4, int arg5);
}

该接口允许其实现直接比较数据流中的记录,无须先把数据流反序列化为对象,这样避免了新建对象而外的开销。

WritableComparator 是对继承自WritableComparable类的RawComparator类的一个通用实现。提供两个主要功能。1,提供对原始的compare()方法的一个默认实现,该方法能够反序列化将在流中进行比较的对象,并调用对象的compare()方法。2,它充当的是RawComparator实例的工厂,例如为了获得IntWritable的comparator,可以直接调用

RawComparator<IntWritable>comparator=WritableComparator.get(IntWritable.class);

下面是《Hadoop权威指南》的例子

package cn.serialization;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.RawComparator;
import org.apache.hadoop.io.Writable;
import org.apache.hadoop.io.WritableComparator;
public class TestWritable {
  //序列化
  public static byte[] serialize(Writable writable) throws IOException{
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    DataOutputStream dataOut= new DataOutputStream(out);
    writable.write(dataOut);
    dataOut.close();
    return out.toByteArray();
  }
  //反序列化
  public static byte[] deserialize(Writable writable, byte[] bytes) throws IOException{
    ByteArrayInputStream in = new ByteArrayInputStream(bytes);
    DataInputStream dataIn = new DataInputStream(in);
    writable.readFields(dataIn);
    dataIn.close();
    return bytes;
  }
  public static void main(String[] args) throws IOException {
    @SuppressWarnings("unchecked")
    RawComparator <IntWritable> comparator = WritableComparator.get(IntWritable.class);
    IntWritable w1 = new IntWritable(163);
    IntWritable w2 = new IntWritable(67);
    byte[] b1 = serialize(w1);
    byte[] b2 = serialize(w2);
    System.out.println(b1);
    System.out.println(b2);
    System.out.println(comparator.compare(w1, w2));//WritableComparator的 compare(),w1>w2 -> 1;w1<w2 -> -1 ; w1=w2 -> 0
  System.out.println(comparator.compare(b1,0,b1.length,b2,0,b2.length));
  }
}

三,Hadoop 序列化框架

尽管大多数MapReduce程序使用Writable类型的key,value,但是不是所有MapReduce API 强制使用。事实上,可以使用任何类型,只要能有一种机制将每个类型进行类型与二进制的来回转换。为此Hadoop提供了一个序列化框架来支持,他们在org.apache.hadoop.io.serializer包中,WritableSerialization类是对Writable类型的Serialization实现。
WritableSerialization类

public class WritableSerialization extends Configured implements Serialization<Writable> {...}

Serializer接口

定义了open()接口,序列化接口,close接口

public interface Serializer<T> {
  void open(OutputStream arg0) throws IOException;
  void serialize(T arg0) throws IOException;
  void close() throws IOException;
}

Deserializer接口

定义了open()接口,反序列化接口,close接口

public interface Deserializer<T> {
  void open(InputStream arg0) throws IOException;
  T deserialize(T arg0) throws IOException;
  void close() throws IOException;
}

Serialization接口

定义了一组接口,判断是否支持输入的类,根据输入的类给出序列化接口和反序列化接口

public interface Serialization<T> {
  boolean accept(Class<?> arg0);
  Serializer<T> getSerializer(Class<T> arg0);
  Deserializer<T> getDeserializer(Class<T> arg0);
}

还有几个接口,可以查看API文档

尽管这可以方便我们在MapReduce使用Java类型,比如String,Integer。但是这还是不如Writable高效。

Hadoop中不使用java Object Serialization的原因

1,Java Object Serialization不够精简,就如本文前面提到的Java Object Serialization序列化后的字节流会包含许多信息,比如类名与对象等。

2,对象在序列化中只存引用,引用可以出现的位置很随机,既可以在序列化的对象前,也可以在其后面,这样就对随机访问和排序造成影响,一旦出错,整个后面的序列化就会全部错误,Writable支持随机访问和排序。因为流中的记录是彼此独立的。

3,.Java序列化每次反序列化都要重新创建对象,内存消耗大,而Writable是可以重用的。

以上所述是小编给大家介绍的Java Object Serialization与 Hadoop 序列化,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对网站的支持!


# java  # 序列化  # object  # serialization  # java结合HADOOP集群文件上传下载  # Java访问Hadoop分布式文件系统HDFS的配置说明  # java使用hadoop实现关联商品统计  # Java执行hadoop的基本操作实例代码  # hadoop中实现java网络爬虫(示例讲解)  # Java/Web调用Hadoop进行MapReduce示例代码  # Hadoop运行时遇到java.io.FileNotFoundException错误的解决方法  # hadoop运行java程序(jar包)并运行时动态指定参数  # java实现对Hadoop的操作  # 利用Java连接Hadoop进行编程  # 的是  # 写到  # 装在  # 是一个  # 几个  # 就会  # 将其  # 所需  # 小编  # 自己的  # 结构化  # 都是  # 包中  # 这是  # 实现了  # 有个  # 都要  # 子类  # 在此 


相关文章: 建站之星伪静态规则如何正确配置?  制作假网页,招聘网的薪资待遇,会有靠谱的吗?一面试又各种折扣?  ,网站推广常用方法?  如何高效生成建站之星成品网站源码?  制作充值网站的软件,做人力招聘为什么要自己交端口钱?  武汉网站制作费用多少,在武汉武昌,建面100平方左右的房子,想装暖气片,费用大概是多少啊?  浅析上传头像示例及其注意事项  内部网站制作流程,如何建立公司内部网站?  Python路径拼接规范_跨平台处理说明【指导】  专业商城网站制作公司有哪些,pi商城官网是哪个?  建站主机SSH密钥生成步骤及常见问题解答?  在线制作视频的网站有哪些,电脑如何制作视频短片?  如何在阿里云虚拟主机上快速搭建个人网站?  建站之星安装需要哪些步骤及注意事项?  如何在企业微信快速生成手机电脑官网?  c# Task.Yield 的作用是什么 它和Task.Delay(1)有区别吗  ,南京靠谱的征婚网站?  胶州企业网站制作公司,青岛石头网络科技有限公司怎么样?  建站之星安装步骤有哪些常见问题?  网站制作话术技巧,网站推广做的好怎么话术?  ,石家庄四十八中学官网?  如何在新浪SAE免费搭建个人博客?  电商网站制作价格怎么算,网上拍卖流程以及规则?  ,交易猫的商品怎么发布到网站上去?  免费制作统计图的网站有哪些,如何看待现如今年轻人买房难的情况?  宁波免费建站如何选择可靠模板与平台?  重庆市网站制作公司,重庆招聘网站哪个好?  香港服务器选型指南:免备案配置与高效建站方案解析  盘锦网站制作公司,盘锦大洼有多少5G网站?  专业制作网站的公司哪家好,建立一个公司网站的费用.有哪些部分,分别要多少钱?  网站制作说明怎么写,简述网页设计的流程并说明原因?  如何在阿里云购买域名并搭建网站?  广东专业制作网站有哪些,广东省能源集团有限公司官网?  广德云建站网站建设方案与建站流程优化指南  如何快速辨别茅台真假?关键步骤解析  济南企业网站制作公司,济南社保单位网上缴费步骤?  建站主机选择指南:服务器配置与SEO优化实战技巧  测试制作网站有哪些,测试性取向的权威测试或者网站?  如何做网站制作流程,*游戏网站怎么搭建?  如何用PHP工具快速搭建高效网站?  建站主机是否等同于虚拟主机?  网站网页制作电话怎么打,怎样安装和使用钉钉软件免费打电话?  南阳网站制作公司推荐,小学电子版试卷去哪里找资源好?  如何优化Golang Web性能_Golang HTTP服务器性能提升方法  用v-html解决Vue.js渲染中html标签不被解析的问题  如何高效完成独享虚拟主机建站?  如何用低价快速搭建高质量网站?  Python如何创建带属性的XML节点  建站主机服务器选型指南与性能优化方案解析  C#怎么使用委托和事件 C# delegate与event编程方法 

您的项目需求

*请认真填写需求信息,我们会在24小时内与您取得联系。