hadoop中Writable类和WritableComparable类、序列化和反序列化

hadoop中Writable类和WritableComparable类、序列化和反序列化,第1张

hadoop中Writable类和WritableComparable类、序列化和反序列化 Writable类和WritableComparable类 序列化和反序列化

序列化: 将内存中的对象转换成字节序列,方便磁盘存储。
反序列化: 将收到的字节序列,转换成内存中的对象。

Writable :对Java基本类型提供封装(short和char除外),使其可以实现序列化和反序列。所有的封装包包含get() 和 set() 方法用于读取或者设置封装的值。在Hadoop中定义一个结构化对象都要实现,使得该结构化对象可以序列化为字节流,字节流也可以反序列化为结构化对象。

WritableComparable:WriteCompareable接口是Wirtable接口的二次封装,提供了compareTo(T o)方法,用于序列化对象的比较的比较MapReduce中所有的key值类型都必须实现这个接口,下面是io包简单的类图关系。

字节流、字符流:
字符和字节详解、Java中字节串和字符串相互转换
Java IO 字节流、字符流详解

1. Writable类

在Hadoop中,Writable接口定义了两个方法:
Write(): 用于将其状态写入二进制格式的DataOutput流。
read(): 用于从二进制格式的DataInput流读取其状态。

package org.apache.hadoop.io;
import java.io.DataOutput;
import java.io.DataInput;
import java.io.IOException;
public interface Writable {
    void write(DataOutput out) throws IOException;
    void readFields(DataInput in) throws IOException;
}

    将来自in(输入流)中对象的字段反序列化。就效率而言,这些实现(implements)应该尝试在可能存在的对象下重用存储。

    基于DataInput和DataOutput,实现一个简单、有效、有序列化协议的序列化对象。

    Hadoop Map-REDUCE框架中的任何key或value类型都必须实现这些接口。

    典型的实现是实现静态的read(DataInput)方法,这个方法构造了一个新的实例;同时调用readFields(DataInput)方法并且返回一个实例。

Implementations typlically

    public class MyWritable implements Writable {
      // Some data     
      private int counter;
      private long timestamp;
      
      public void write(DataOutput out) throws IOException {
        out.writeInt(counter);
        out.writeLong(timestamp);
      }
      
      public void readFields(DataInput in) throws IOException {
        counter = in.readInt();
        timestamp = in.readLong();
      }
      
      public static MyWritable read(DataInput in) throws IOException {
        MyWritable w = new MyWritable();
        w.readFields(in);
        return w;
      }
    }

DataOutput和DataInput
DataOutput接口用于将数据从任意 Java 基本类型转换为一系列字节,并将这些字节写入二进制流。同时还提供了一个将 String 转换成 UTF-8 修改版格式并写入所得到的系列字节的工具。

DataInput接口提供用于读取二进制流字节并重建为任何java原始数据类型,也提供了一个转换为UTF-8编码的字符串类型方法。

2. WritableComparable类

WritableComparable继承了Writable接口和Comparable接口,由于WritableComparable中没有定义要实现的方法,所以继承这个接口,要实现的方法都是Writable接口和Comparable接口中的方法。

Writable接口
实现write和readFields方法,write是要对out对象进行序列化 *** 作,readFields是对in对象进行反序列化 *** 作。

public interface Writable {
  
  void write(DataOutput out) throws IOException;

  
  void readFields(DataInput in) throws IOException;
}

Comparable接口
将调用该方法的对象和传入参数对象进行比较

public int compareTo(T o);

返回值有三种:
负整数,此时调用该方法的对象小于指定对象;
0,二者相等;
正整数,调用该方法的对象大于指定对象。

针对key自定义排序示例

public class MyWritableComparable implements WritableComparable {
   // Some data
   private int counter;
   private long timestamp;

   public void write(DataOutput out) throws IOException {
     out.writeInt(counter);
     out.writeLong(timestamp);
   }

   public void readFields(DataInput in) throws IOException {
     counter = in.readInt();
     timestamp = in.readLong();
   }

   public int compareTo(MyWritableComparable o) {
     int thisValue = this.value;
     int thatValue = o.value;
     return (thisValue < thatValue ? -1 : (thisValue==thatValue ? 0 : 1));
   }

    public int hashCode() {
     final int prime = 31;
     int result = 1;
     result = prime * result + counter;
     result = prime * result + (int) (timestamp ^ (timestamp >>> 32));
     return result
        }
 }

注意,实现序列化和反序列化方法时,写入和读取属性的顺序一定要相同!!!实现完成之后,这个实现类就可以作为Map阶段输入或者输出数据的key类型,进行输出。在compareTo方法中实现自定义排序。

3. Java基本类型的Writable类


IntWritable 和 VIntWritable 这两个的区别是 IntWriable是固定的4个字节,而 VintWritable 是1~5个字节,是可以变化的。相比与定长格式,变长格式有什么优点:

(1)定长格式适合对整个值域空间中分布均匀的数值进行编码,大多数数值变量的分布都不均匀,而采用变长格式一般更节省空间。

(2)变长格式的 VIntWritable 和 VLlongWritable 可以转换,因为他们的编码实际上一致。选择变长格式,更有增长空间。

参考资料:
Hadoop中Writable类

Hadoop源码解析之Writable类

接口 DataOutput

(一)java.io.DataInput接口及源码详解

自定义排序WritableComparable

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5715683.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存