设为首页 收藏本站
查看: 1385|回复: 0

[经验分享] 自定义Hadoop的可序列化类

[复制链接]

尚未签到

发表于 2018-11-1 08:11:54 | 显示全部楼层 |阅读模式
  java原生语言中要想一个自定义类可序列化,很简单,只要让这个类实现java.io.Serializable接口就可以了,但是在Hadoop框架中,要想让自定义类可以被序列化,我们必须手动让其实现WritableCompable接口并且实现write(),readFields(),compareTo()方法。
  下面就是一个我们自定义的可序列化的类:
  


  • /*
  • */
  • package com.charles.writable;

  • import java.io.DataInput;
  • import java.io.DataOutput;
  • import java.io.IOException;


  • import org.apache.hadoop.io.IntWritable;
  • import org.apache.hadoop.io.Text;
  • import org.apache.hadoop.io.WritableComparable;

  • /**
  • *
  • * Description: 这是自定义的Hadoop序列化类,它可以用Hadoop序列化反序列化这个类
  • *
  • * @author charles.wang
  • * @created Jun 2, 2012 11:19:25 AM
  • *
  • */
  • public class PersonWritable implements WritableComparable {

  •     private Text name;
  •     private IntWritable age;
  •     private Text title;

  •     public PersonWritable(){
  •        set("someperson",0,"sometitle");
  •     }

  •     public PersonWritable(String name ,int age, String title){
  •         set(name,age,title);
  •     }


  •     public void set(String name ,int age,String title){
  •         this.name =  new Text(name);

  •         age=(age>0)?age:1;
  •         this.age = new IntWritable(age);

  •         this.title=  new Text(title);
  •     }


  •     /**
  •      *  这个方法用于定义序列化过程,它把这个对象的所有字段依次序列化
  •      */
  •     @Override
  •     public void write(DataOutput out) throws IOException {
  •         // TODO Auto-generated method stub

  •         name.write(out);
  •         age.write(out);
  •         title.write(out);

  •     }

  •     /**
  •      *  这个方法用于定义反序列化过程,它吧序列化后的DataInput的内容还原为Hadoop对象
  •      */
  •     @Override
  •     public void readFields(DataInput in) throws IOException {
  •         // TODO Auto-generated method stub

  •         name.readFields(in);
  •         age.readFields(in);
  •         title.readFields(in);

  •     }

  •     /**
  •      * 这是用于2个序列化对象之间的比较
  •      */
  •     @Override
  •     public int compareTo(PersonWritable pO) {
  •         // TODO Auto-generated method stub
  •         int cmp1 = name.compareTo(pO.name);
  •         if(cmp1 != 0){
  •             return cmp1;
  •         }

  •         int cmp2 = age.compareTo(pO.age);
  •         if(cmp2 !=0){
  •             return cmp2;
  •         }

  •         int cmp3 = title.compareTo(pO.title);
  •         return cmp3;
  •     }

  •     /**
  •      * 定义hashcode是个好习惯,我们还是使用最常用的字段分别乘以不同的素数然后相加的方法
  •      */
  •     @Override
  •     public int hashCode(){
  •         return name.hashCode()*71+ age.hashCode()*73+title.hashCode()*127;
  •     }

  •     @Override
  •     public boolean equals (Object o ){
  •         if ( o instanceof PersonWritable){

  •             PersonWritable pw = (PersonWritable) o;
  •             boolean equals = name.equals(pw.name) && age.equals(pw.age) && title.equals(pw.title);
  •             return equals;
  •         }
  •         return false;
  •     }

  •     @Override
  •     public String toString(){
  •         StringBuffer sb = new StringBuffer();
  •         sb.append("[");
  •         sb.append("姓名: "+name+",");
  •         sb.append("年龄: "+age+",");
  •         sb.append("头衔: "+title);
  •         sb.append("]");
  •         return sb.toString();
  •     }

  • }
  

  为了方便演示序列化前后的内容,我们定义了一个工具方法,这个方法可以用于跟踪序列化和反序列化的中间产物:
  


  • /*
  • */
  • package com.charles.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.Writable;

  • /**
  • *
  • * Description: 这个类提供了工具方法来记录序列化的轨迹
  • * 因为,在hadoop中序列化和反序列化都是在Writable接口中进行的,Writable是被序列化的Hadoop对象
  • * 所以我们把序列化的产物存到字节数组中从而可以捕捉到内容
  • *
  • * @author charles.wang
  • * @created Jun 2, 2012 9:32:41 AM
  • *
  • */
  • public class HadoopSerializationUtil {

  •     //这个方法可以把Hadoop的对象(Writable表示这个是可以序列化的)序列化到字节数组中,
  •     //然后把字节数组中的内容返回出来
  •     //入参,被序列化的数值对象
  •     //返回值:序列化后的字节数组
  •     public static byte[] serialize(Writable writable) throws IOException {
  •         //创建一个字节数组
  •          ByteArrayOutputStream out = new ByteArrayOutputStream();
  •          //创建一个DataOutputStream,并且包装字节数组,用于存放序列化后的字节流
  •          DataOutputStream dataout =  new DataOutputStream(out);
  •          //让参数的Hadoop对象序列化到字节流中
  •          writable.write(dataout);
  •          dataout.close();
  •          //返回序列化后的字节流
  •          return out.toByteArray();
  •     }

  •     //这个方法用于反序列化一个字节数组成Hadoop Writable对象
  •     //入参1:反序列化后的Writable对象存放在这个参数中
  •     //入参2:被反序列化的字节数组
  •     public static void deserialize(Writable writable,byte[] bytes) throws Exception{

  •         //打开一个字节数组输入流让其指向即将要被处理的字节数组(第二个参数)
  •         ByteArrayInputStream in = new ByteArrayInputStream(bytes);
  •         //打开一个DataInputStream
  •         DataInputStream datain = new DataInputStream(in);
  •         //让Hadoop框架反序列化这个字节数组,还原后的Writable对象存放到第一个参数中
  •         writable.readFields(datain);
  •         datain.close();
  •     }



  • }
  

  最后,我们用一个Demo例子来演示序列化和反序列化我们自定义的类的对象:
  


  • /*
  • */
  • package com.charles.writable;

  • import org.apache.hadoop.util.StringUtils;


  • /**
  • *
  • * Description: 这个例子用于展示自定义的Hadoop序列化类是否工作正常
  • *
  • * @author charles.wang
  • * @created Jun 2, 2012 11:40:01 AM
  • *
  • */
  • public class HadoopObjectSerializationDemo {


  •     public static void main(String [] args) throws Exception{

  •         //第一个实验,把我们自定义的Hadoop可序列化对象进行序列化
  •         System.out.println("实验1: 序列化");
  •         PersonWritable originalPersonWritable = new PersonWritable("Charles Wang" ,26 ,"Technical Lead");
  •         String typeInfo= "被测试的自定义Hadoop可序列化类类型为: "+originalPersonWritable.getClass().getName()+"\n";
  •         String primaryPersonWritableInfo = "序列化前对象为:  "+originalPersonWritable.toString()+"\n";
  •         //开始序列化过程
  •         byte[] serializedHadoopValue =HadoopSerializationUtil.serialize(originalPersonWritable);
  •         String lengthInfo= "序列化后的字节数组长度为: "+serializedHadoopValue.length+"\n";
  •         String serializeValueInfo= "序列化后的值为: " +StringUtils.byteToHexString(serializedHadoopValue)+"\n";

  •         System.out.println(typeInfo+primaryPersonWritableInfo+lengthInfo+serializeValueInfo+"\n");

  •         System.out.println();

  •         //第二个实验,把我们序列化之后的字节数组反序列化为原始Hadoop对象
  •         System.out.println("实验2:反序列化");
  •         PersonWritable restoredPersonWritable = new PersonWritable();
  •         String originalByteArrayInfo="被反序列化的字节数组内容为: "+StringUtils.byteToHexString(serializedHadoopValue)+"\n";
  •         //开始反序列化过程
  •         HadoopSerializationUtil.deserialize(restoredPersonWritable, serializedHadoopValue);
  •         String restoredValueInfo = "反序列化之后的Writable对象为: "+restoredPersonWritable.toString();
  •         System.out.println(originalByteArrayInfo+restoredValueInfo+"\n");
  •     }
  • }
  

  最终结果如下,从而证明,我们自定义的Hadoop可序列化类是正确的:
  


  • 实验1: 序列化
  • 被测试的自定义Hadoop可序列化类类型为: com.charles.writable.PersonWritable
  • 序列化前对象为:  [姓名: Charles Wang,年龄: 26,头衔: Technical Lead]
  • 序列化后的字节数组长度为: 32
  • 序列化后的值为: 0c436861726c65732057616e670000001a0e546563686e6963616c204c656164



  • 实验2:反序列化
  • 被反序列化的字节数组内容为: 0c436861726c65732057616e670000001a0e546563686e6963616c204c656164
  • 反序列化之后的Writable对象为: [姓名: Charles Wang,年龄: 26,头衔: Technical Lead]



运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-629142-1-1.html 上篇帖子: Hadoop 序列化的研究 下篇帖子: 用Hadoop管理界面来分析Map-Reduce作业
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表