1. 序列化反序列化
1.1 序列化反序列化是什么
序列化: 是将内存中的对象转换称为字节序列,以便持久化到磁盘中或用于网络传输
反序列化: 将字节序列转换称为内存中的对象
1.2 JDK 序列化反序列化
Java 中,如果需要序列化,需要实现 java.io.Serializable 接口,利用序列化版本ID serialVersionUID 来标识版本。
JDK 需要借助 ObjectOutputStream (writeObject(Object) )和 ObjectInputStream (readObject() )分别实现序列化反序列化。
1.3 Hadoop 序列化反序列化
Hadoop 不适用 JDK 序列化,是因为利用 Serializable 序列化后会附带很多额外的信息,不便于数据的网络传输。
Hadoop 实现的序列化机制为 Writable 。
1.4 Hadoop 序列化的意义
Hadoop 在集群之间进行通讯或者 RPC 调用的时候,需要序列化,而且要求序列化要快,且体积要小,占用带宽要小。所以必须理解 Hadoop 的序列化机制。
序列化和反序列化在分布式数据处理领域经常出现:进程通信和永久存储。然而Hadoop中各个节点的通信是通过远程调用(RPC)实现的,那么就不能使用 JDK 序列化,所以 Hadoop 自己实现了一套序列化机制。
Hadoop 序列化特点:
- 紧凑:高校使用存储空间
- 快速:读写数据的额外开销小
- 可扩展:原始序列化方式支持新协议的报文
- 互操作:支持多种语言的交互
1.5 序列化类型
Java 类型 | Hadoop Writable 类型 |
---|
boolean | BooleanWritable | byte | ByteWritable | int | IntWritable | float | FloatWritable | long | LongWritable | double | DoubleWritable | string | Text | map | MapWritable | array | ArrayWritable |
2. Writable 自定义实现
Writable 用于在对象和字节序列之间做转换。
自定义实现需要注意几点:
- 必须要实现 Writable 接口
- 需要提供无参构造,应为反序列化需要反射调用空参构造函数
- 重写序列、反序列方法,且序列和反序列的顺序保持一致
- 如果后期需要指定 key 排序,还需要实现 Comparable 接口
2.1 窥见源码
Writable 接口中只有两个方法
write :用于序列化操作readFields :用于反序列化操作
public interface Writable {
void write(DataOutput var1) throws IOException;
void readFields(DataInput var1) throws IOException;
}
如果需要比较,我们可以直接实现WritableComparable 接口,该接口只是继承了两个接口类,因此还需要实现 Comparable 的 compareTo 方法。
@Public
@Stable
public interface WritableComparable<T> extends Writable, Comparable<T> {
}
public interface Comparable<T> {
public int compareTo(T o);
}
2.2 自定义 Bean
比如:对日志文件进行相关信息统计
import org.apache.hadoop.io.Writable;
import org.apache.hadoop.io.WritableComparable;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
public class WritableUser implements WritableComparable<WritableUser> {
long id;
String name;
int age;
boolean sex;
int money;
@Override
public void write(DataOutput dataOutput) throws IOException {
dataOutput.writeLong(this.id);
dataOutput.writeUTF(this.name);
dataOutput.writeInt(this.age);
dataOutput.writeBoolean(this.sex);
dataOutput.writeInt(this.money);
}
@Override
public void readFields(DataInput dataInput) throws IOException {
this.id = dataInput.readLong();
this.name = dataInput.readUTF();
this.age = dataInput.readInt();
this.sex = dataInput.readBoolean();
this.money = dataInput.readInt();
}
@Override
public int compareTo(WritableUser o) {
if (this.age == o.age){
return -Integer.compare( this.money, o.money);
} else {
return -Integer.compare( this.age, o.age);
}
}
public WritableUser() {
}
public WritableUser(long id, String name, int age, boolean sex, int money) {
this.id = id;
this.name = name;
this.age = age;
this.sex = sex;
this.money = money;
}
public void set(long id, String name, int age, boolean sex, int money) {
this.id = id;
this.name = name;
this.age = age;
this.sex = sex;
this.money = money;
}
@Override
public String toString() {
return "WritableUser{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
", sex=" + sex +
", money=" + money +
'}';
}
}
3. 写在最后
只需要序列化时,实现 Writable ,如果还需要排序,可实现 WritableComparable 。
如果想要降序排列,在返回值前加个负号(- )
?
???END???
|