Hadoop如何实现自定义的Writable
来源:互联网 发布:mysql front5.3 乱码 编辑:程序博客网 时间:2024/05/04 02:08
Hadoop自带一系列有用的Writable实现,可以满足绝大多数用途。但有时,我们需要编写自己的自定义实现。通过自定义Writable,我们能够完全控制二进制表示和排序顺序。Writable是MapReduce数据路径的核心,所以调整二进制表示对其性能有显著影响。现有的Hadoop Writable应用已得到很好的优化,但为了对付更复杂的结构,最好创建一个新的Writable类型,而不是使用已有的类型。
为了演示如何创建一个自定义Writable,我们编写了一个表示一对字符串的实现,名为TextPair。
import
java.io.*;
import
org.apache.hadoop.io.*;
public
class
TextPair
implements
WritableComparable<TEXTPAIR> {
private
Text first;
private
Text second;
public
TextPair() {
set(
new
Text(),
new
Text());
}
public
TextPair(String first, String second) {
set(
new
Text(first),
new
Text(second));
}
public
TextPair(Text first, Text second) {
set(first, second);
}
public
void
set(Text first, Text second) {
this
.first = first;
this
.second = second;
}
public
Text getFirst() {
return
first;
}
public
Text getSecond() {
return
second;
}
@Override
public
void
write(DataOutput out)
throws
IOException {
first.write(out);
second.write(out);
}
@Override
public
void
readFields(DataInput in)
throws
IOException {
first.readFields(in);
second.readFields(in);
}
@Override
public
int
hashCode() {
return
first.hashCode() *
163
+ second.hashCode();
}
@Override
public
boolean
equals(Object o) {
if
(o
instanceof
TextPair) {
TextPair tp = (TextPair) o;
return
first.equals(tp.first) && second.equals(tp.second);
}
return
false
;
}
@Override
public
String toString() {
return
first +
"\t"
+ second;
}
@Override
public
int
compareTo(TextPair tp) {
int
cmp = first.compareTo(tp.first);
if
(cmp !=
0
) {
return
cmp;
}
return
second.compareTo(tp.second);
}
}</TEXTPAIR>
通过委托给每个Text对象本身,TextPair的write()方法依次序列化输出流中的每一个Text对象。同样,也通过委托给Text对象本身,readFields()反序列化输人流中的字节。DataOutput和DataInput接口有丰富的整套方法用于序列化和反序列化Java基本类型,所以在一般情况下,我们能够完全控制Writable对象的数据传输格式。
正如为Java写的任意值对象一样,我们会重写java.lang.Object的hashCode()方法,equals()方法和toString()方法。HashPartitioner使用hashCode()方法来选择reduce分区,所以应该确保写一个好的哈希函数来确保reduce函数的分区在大小上是相当的。
TextPair是WritableComparable的实现,所以它提供了compareTo()方法的实现,加入我们希望的顺序:它通过一个一个String逐个排序。请注意,TextPair不同于前面的TextArrayWritable类(除了它可以存储Text对象数之外),因为TextArrayWritable只是一个Writable,而不是WritableComparable。
实现一个快速的RawComparator
上例中所示代码能够有效工作,但还可以进一步优化。正如前面所述,在MapReduce中,TextPair被用作键时,它必须被反序列化为要调用的compareTo()方法的对象。是否可以通过查看其序列化表示的方式来比较两个TextPair对象。
事实证明,我们可以这样做,因为TextPair由两个Text对象连接而成,二进制Text对象表示是一个可变长度的整型,包含UTF-8表示的字符串中的字节数,后跟UTF-8字节本身。关键在于读取开始的长度。从而得知第一个Text对象的字节表示有多长,然后可以委托Text对象的RawComparator,然后利用第一或者第二个字符串的偏移量来调用它。下面例子给出了具体方法(注意,该代码嵌套在TextPair类中)。
public
static
class
Comparator extends WritableComparator {
private
static
final Text.Comparator TEXT_COMPARATOR =
new
Text.Comparator();
public
Comparator() {
super(TextPair.
class
);
}
@Override
public
int
compare(byte[] b1,
int
s1,
int
l1,
byte[] b2,
int
s2,
int
l2) {
try
{
int
firstL1 = WritableUtils.decodeVIntSize(b1[s1]) + readVInt(b1, s1);
int
firstL2 = WritableUtils.decodeVIntSize(b2[s2]) + readVInt(b2, s2);
int
cmp = TEXT_COMPARATOR.compare(b1, s1, firstL1, b2, s2, firstL2);
if
(cmp != 0) {
return
cmp;
}
return
TEXT_COMPARATOR.compare(b1, s1 + firstL1, l1 - firstL1,
b2, s2 + firstL2, l2 - firstL2);
}
catch
(IOException e) {
throw
new
IllegalArgumentException(e);
}
}
}
static
{
WritableComparator.define(TextPair.
class
,
new
Comparator());
}
静态代码块注册原始的comparator以便MapReduce每次看到TextPair类,就知道使用原始comparator作为其默认comparator。
自定义comparator
从TextPair可知,编写原始的cornparator比较费力,因为必须处理字节级别的细节。如果需要编写自己的实现,org.apache.hadoop.io包中Writable的某些前瞻性实现值得研究研究。WritableUtils的有效方法也比较非常方便。
如果可能,还应把自定义comparator写为RawComparators。这些comparator实现的排序顺序不同于默认comparator定义的自然排序顺序。下面的例子显示了TextPair的comparator,称为First Comparator。只考虑了一对Text对象中的第一个字符串。请注意,我们重写了compare()方法使其使用对象进行比较,所以两个compare()方法的语义是相同的。
public
static
class
FirstComparator extends WritableComparator {
private
static
final Text.Comparator TEXT_COMPARATOR =
new
Text.Comparator();
public
FirstComparator() {
super(TextPair.
class
);
}
@Override
public
int
compare(byte[] b1,
int
s1,
int
l1,
byte[] b2,
int
s2,
int
l2) {
try
{
int
firstL1 = WritableUtils.decodeVIntSize(b1[s1]) + readVInt(b1, s1);
int
firstL2 = WritableUtils.decodeVIntSize(b2[s2]) + readVInt(b2, s2);
return
TEXT_COMPARATOR.compare(b1, s1, firstL1, b2, s2, firstL2);
}
catch
(IOException e) {
throw
new
IllegalArgumentException(e);
}
}
@Override
public
int
compare(WritableComparable a, WritableComparable b) {
if
(a instanceof TextPair && b instanceof TextPair) {
return
((TextPair) a).first.compareTo(((TextPair) b).first);
}
return
super.compare(a, b);
}
}
- Hadoop如何实现自定义的Writable
- hadoop writable的实现
- Hadoop自定义Writable实现二次排序
- 实现Hadoop的Writable接口Implementing Writable interface of Hadoop
- 自定义Hadoop Writable
- Hadoop 自定义Writable NullPointerException
- Hadoop 自定义Writable NullpointerException
- hadoop 自定义Writable
- Hadoop(11) 自定义Writable
- 关于hadoop的mapreduce编程中自定义key,value建立的类实现writable接口
- 利用hadoop命令rcc生成Record 一种简单的方式实现自定义的writable对象
- Hadoop自定义实现Writable/WritableComparable接口的类方法及应用
- Hadoop 实现Writable接口
- Hadoop Serialization -- hadoop序列化详解 (3)【ObjectWritable,集合Writable以及自定义的Writable】
- Hadoop Serialization -- hadoop序列化详解 (3)【ObjectWritable,集合Writable以及自定义的Writable】
- Hadoop中MultipleOutputs的应用,以及自定义Writable
- Writable实现类 与 自定义Writable接口
- hadoop的WritableComparable与Writable
- JSP页面跳转的五种方法
- The 9th SWJTU-CPC Qualification Round Tutorials
- android 图片设置圆角
- EXP-00091: Exporting questionable statistics
- Hibernate之条件查询(Criteria Queries)
- Hadoop如何实现自定义的Writable
- 广告牌技术教程:欺骗-快速但不容易
- struts(三)
- 小米营销重心转移,回归性能本身
- 炒股票学习培训,从入门到经常抓涨停的技巧之二___投资定位
- <tx:method ... read-only="true" /> read-only提高查询性能的原因
- 第五次C程序设计实验报告
- 三层架构——实体类
- hdu 2617