序列化就是把内存中的对象,转换成字节序列(或其余数据传输协议)以便于存储(持久化)和网络传输。 java
反序列化就是将收到字节序列(或其余数据传输协议)或者是硬盘的持久化数据,转换成内存中的对象。apache
Hadoop拥有一套本身的序列化机制。网络
Java的序列化是一个重量级序列化框架(Serializable),一个对象被序列化后,会附带不少额外的信息(各类校验信息,header,继承体系等),不便于在网络中高效传输。因此,hadoop本身开发了一套序列化机制(Writable),他具备精简、高效的特色。框架
Hadoop之父Doug Cutting(道格卡丁)解释道:“由于Java的序列化机制太过复杂了,而我认为须要有一个精简的机制,能够用于精确控制对象的读和写,这个机制将是Hadoop的核心。使用Java序列化虽然能够得到一些控制权,但用起来很是纠结。不用RMI(远程方法调用)也是出于相似的考虑。”ide
咱们经过经常使用的Java数据类型对应的hadoop数据序列化类型 |Java类型|Hadoop Writable类型| |-|-| |boolean |BooleanWritable| |byte |ByteWritable| |int |IntWritable| |float |FloatWritable| |long |LongWritable| |double |DoubleWritable| |string |Text| |map |MapWritable| |array| ArrayWritable|函数
在具体案例中,咱们能够根据实际需求,若是类型能够用简单类型胜任的话,在此表中寻找到对应的参考。oop
不少状况下,基础类型是没法知足咱们的业务需求的,一般咱们的输入输出极可能都是一些实体化的类型映射。基于这种状况,咱们就须要自定义writable类型。this
自定义bean对象要想序列化传输,必须实现序列化接口,须要参考以下规则:code
setter方法中,推荐再增长一个set方法,用于一次性设置全部的合并字段。对象
以下是一个简单的自定义Writable类型
package com.zhaoyi.phoneflow; import org.apache.hadoop.io.Writable; import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; public class FlowBean implements Writable { private long upFlow;// 上行流量 private long downFlow;// 下行流量 private long totalFlow;// 总流量 // 无参构造 public FlowBean() { } public FlowBean(long upFlow, long downFlow) { this.upFlow = upFlow; this.downFlow = downFlow; this.totalFlow = upFlow + downFlow; } // 序列化 public void write(DataOutput out) throws IOException { out.writeLong(upFlow); out.writeLong(downFlow); out.writeLong(totalFlow); } // set方法,一次性设置属性 public void set(long upFlow, long downFlow){ this.upFlow = upFlow; this.downFlow = downFlow; this.totalFlow = upFlow + downFlow; } // 反序列化 - 顺序和序列化保持一致 public void readFields(DataInput in) throws IOException { this.upFlow = in.readLong(); this.downFlow = in.readLong(); this.totalFlow = in.readLong(); } public long getUpFlow() { return upFlow; } public long getDownFlow() { return downFlow; } public long getTotalFlow() { return totalFlow; } public void setUpFlow(long upFlow) { this.upFlow = upFlow; } public void setDownFlow(long downFlow) { this.downFlow = downFlow; } public void setTotalFlow(long totalFlow) { this.totalFlow = totalFlow; } // 使用制表符分隔 @Override public String toString() { return "upFlow=" + upFlow + "\t" + downFlow + "\t" + totalFlow; } }