自定义Writable、RawComparatorWritable、comparators(转)
自定义Writable
hadoop虽然已经实现了一些非常有用的Writable,而且你可以使用他们的组合做很多事情,但是如果你想构造一些更加复杂的结果,你可以自定义Writable来达到你的目的,我们以注释的方式对自定义Writable进行讲解(不许说我只帖代码占篇幅哦,姿势写在注释里了):
- package com.sweetop.styhadoop;
- import org.apache.hadoop.io.Text;
- import org.apache.hadoop.io.WritableComparable;
- import java.io.DataInput;
- import java.io.DataOutput;
- import java.io.IOException;
- /**
- * Created with IntelliJ IDEA.
- * User: lastsweetop
- * Date: 13-7-17
- * Time: 下午8:50
- * To change this template use File | Settings | File Templates.
- */
- public class EmploeeWritable implements WritableComparable<EmploeeWritable>{
- private Text name;
- private Text role;
- /**
- * 必须有默认的构造器皿,这样Mapreduce方法才能创建对象,然后通过readFields方法从序列化的数据流中读出进行赋值
- */
- public EmploeeWritable() {
- set(new Text(),new Text());
- }
- public EmploeeWritable(Text name, Text role) {
- set(name,role);
- }
- public void set(Text name,Text role) {
- this.name = name;
- this.role = role;
- }
- public Text getName() {
- return name;
- }
- public Text getRole() {
- return role;
- }
- /**
- * 通过成员对象本身的write方法,序列化每一个成员对象到输出流中
- * @param dataOutput
- * @throws IOException
- */
- @Override
- public void write(DataOutput dataOutput) throws IOException {
- name.write(dataOutput);
- role.write(dataOutput);
- }
- /**
- * 同上调用成员对象本身的readFields方法,从输入流中反序列化每一个成员对象
- * @param dataInput
- * @throws IOException
- */
- @Override
- public void readFields(DataInput dataInput) throws IOException {
- name.readFields(dataInput);
- role.readFields(dataInput);
- }
- /**
- * implements WritableComparable必须要实现的方法,用于比较 排序
- * @param emploeeWritable
- * @return
- */
- @Override
- public int compareTo(EmploeeWritable emploeeWritable) {
- int cmp = name.compareTo(emploeeWritable.name);
- if(cmp!=0){
- return cmp;
- }
- return role.compareTo(emploeeWritable.role);
- }
- /**
- * MapReduce需要一个分割者(Partitioner)把map的输出作为输入分成一块块的喂给多个reduce)
- * 默认的是HashPatitioner,他是通过对象的hashcode函数进行分割,所以hashCode的好坏决定
- * 了分割是否均匀,他是一个很关键性的方法。
- * @return
- */
- @Override
- public int hashCode() {
- return name.hashCode()*163+role.hashCode();
- }
- @Override
- public boolean equals(Object o) {
- if(o instanceof EmploeeWritable){
- EmploeeWritable emploeeWritable=(EmploeeWritable)o;
- return name.equals(emploeeWritable.name) && role.equals(emploeeWritable.role);
- }
- return false;
- }
- /**
- * 如果你想自定义TextOutputformat作为输出格式时的输出,你需要重写toString方法
- * @return
- */
- @Override
- public String toString() {
- return name+"\t"+role;
- }
- }
Writable对象是可更改的而且经常被重用,因此尽量避免在write和readFields中分配对象。
自定义RawComparatorWritable
- public static class Comparator extends WritableComparator{
- private static final Text.Comparator TEXT_COMPARATOR= new Text.Comparator();
- protected Comparator() {
- super(EmploeeWritable.class);
- }
- @Override
- public int compare(byte[] b1, int s1, int l1, byte[] b2, int s2, int l2) {
- try {
- /**
- * name是Text类型,Text是标准的UTF-8字节流,
- * 由一个变长整形开头表示Text中文本所需要的长度,接下来就是文本本身的字节数组
- * decodeVIntSize返回变长整形的长度,readVInt表示文本字节数组的长度,加起来就是第一个成员name的长度
- */
- int nameL1= WritableUtils.decodeVIntSize(b1[s1])+readVInt(b1,s1);
- int nameL2=WritableUtils.decodeVIntSize(b2[s2])+readVInt(b2,s2);
- //和compareTo方法一样,先比较name
- int cmp = TEXT_COMPARATOR.compare(b1,s1,nameL1,b2,s2,nameL2);
- if(cmp!=0){
- return cmp;
- }
- //再比较role
- return TEXT_COMPARATOR.compare(b1,s1+nameL1,l1-nameL1,b2,s2+nameL2,l2-nameL2);
- } catch (IOException e) {
- throw new IllegalArgumentException();
- }
- }
- static {
- //注册raw comprator,更象是绑定,这样MapReduce使用EmploeeWritable时就会直接调用Comparator
- WritableComparator.define(EmploeeWritable.class,new Comparator());
- }
- }
我们没有直接去实现RawComparator而是继承于WritableComparator,因为WritableComparator提供了很多便捷的方法,并且对compare有个默认的实现。写compare方法时一定要小心谨慎,因为都是在字节上操作,可以好好参考下源代码里的一些Writable中Comparator的写法,另外多看下WritableUtils也是由必要的,他里面有很多简便的方法可以使用。
自定义comparators
- public static class NameComparator extends WritableComparator{
- private static final Text.Comparator TEXT_COMPARATOR= new Text.Comparator();
- protected NameComparator() {
- super(EmploeeWritable.class);
- }
- @Override
- public int compare(byte[] b1, int s1, int l1, byte[] b2, int s2, int l2) {
- try {
- int nameL1= WritableUtils.decodeVIntSize(b1[s1])+readVInt(b1,s1);
- int nameL2=WritableUtils.decodeVIntSize(b2[s2])+readVInt(b2,s2);
- return TEXT_COMPARATOR.compare(b1,s1,nameL1,b2,s2,nameL2);
- } catch (IOException e) {
- throw new IllegalArgumentException();
- }
- }
- @Override
- public int compare(WritableComparable a, WritableComparable b) {
- if(a instanceof EmploeeWritable && b instanceof EmploeeWritable){
- return ((EmploeeWritable)a).name.compareTo(((EmploeeWritable)b).name);
- }
- return super.compare(a,b);
- }
- }
自定义Writable、RawComparatorWritable、comparators(转)的更多相关文章
- 5.3.3 自定义writable和RawComparatorWritable
5.3.3 自定义writable (1)构造员工writable Hadoop虽然已经实现了一些非常有用的Writable,而且你可以使用他们的组合做很多事情,但是如果你想构造一些更加复杂的结果,你 ...
- 读取SequenceFile中自定义Writable类型值
1)hadoop允许程序员创建自定义的数据类型,如果是key则必须要继承WritableComparable,因为key要参与排序,而value只需要继承Writable就可以了.以下定义一个Doub ...
- Hadoop Serialization -- hadoop序列化详解 (3)【ObjectWritable,集合Writable以及自定义的Writable】
前瞻:本文介绍ObjectWritable,集合Writable以及自定义的Writable TextPair 回顾: 前面了解到hadoop本身支持java的基本类型的序列化,并且提供相应的包装实现 ...
- 自定义排序及Hadoop序列化
自定义排序 将两列数据进行排序,第一列按照升序排列,当第一列相同时,第二列升序排列. 在map和reduce阶段进行排序时,比较的是k2.v2是不参与排序比较的.如果要想让v2也进行排序,需要把k2和 ...
- MapReduce实例-倒排索引
环境: Hadoop1.x,CentOS6.5,三台虚拟机搭建的模拟分布式环境 数据:任意数量.格式的文本文件(我用的四个.java代码文件) 方案目标: 根据提供的文本文件,提取出每个单词在哪个文件 ...
- 重新认识mapreduce
写这篇文章,是因为最近遇到了mapreduce的二次排序问题.以前的理解不完全正确.首先看一下mapreduce的过程 相信这张图熟悉MR的人都应该见过,再来一张图 wordcount也不细说了,ha ...
- [大牛翻译系列]Hadoop(13)MapReduce 性能调优:优化洗牌(shuffle)和排序阶段
6.4.3 优化洗牌(shuffle)和排序阶段 洗牌和排序阶段都很耗费资源.洗牌需要在map和reduce任务之间传输数据,会导致过大的网络消耗.排序和合并操作的消耗也是很显著的.这一节将介绍一系列 ...
- 一站式Hadoop&Spark云计算分布式大数据和Android&HTML5移动互联网解决方案课程(Hadoop、Spark、Android、HTML5)V2的第一门课程
Hadoop是云计算的事实标准软件框架,是云计算理念.机制和商业化的具体实现,是整个云计算技术学习中公认的核心和最具有价值内容. 如何从企业级开发实战的角度开始,在实际企业级动手操作中深入浅出并循序渐 ...
- [BigData]关于Hadoop学习笔记第三天(PPT总结)(一)
课程安排 MapReduce原理*** MapReduce执行过程** 数据类型与格式*** Writable接口与序列化机制*** ---------------------------加深拓展- ...
随机推荐
- Linux 性能检测 - CentOS 安装 paramon
简介 paramon是一款性能检测工具. 数据发送:cnt 数据接收:svr Continue...
- iOS Node Conflict svn冲突
当出现这个冲突时,应该是我add的文件,和同事处理的方法有冲突导致的. 这个的解决办法是:先revert这个文件,然后再update.
- miaov- 自动生成正V反V大于号V小于号V楼梯等图案
1. 核心:控制 数量的长度-1-i的位置,是放在left上还是top上?是放在前面还是后面! <!DOCTYPE html> <html lang="en"&g ...
- SWD模式连接与注意事项
JTAG模式与SWD模式连接图 SWD 仿真模式概念简述 一.SWD 和传统的调试方式区别 1. SWD 模式比 JTAG 在高速模式下面更加可靠. 在大数据量的情况下面 JTAG 下载程序会失败, ...
- Date and Time Pattern
The following examples show how date and time patterns are interpreted in the U.S. locale. The given ...
- Javascript位置 body之前、后执行顺序
简介:当页面加载的时候,嵌入html标记的js代码和位于<body></body>之间的js代码将被执行:当调用的时候,位于<head></head>之 ...
- Linux命令行–更多bash shell命令(转)
4.1.1 探查程序 ps 命令 默认情况下,ps命令只会显示运行在当前控制台下的属于当前用户进程的进程 显示的当前进程的项目 进程号 运行在哪个终端(tty) 进程占用的CPU时间 Linux系统支 ...
- ComparatorChain、BeanComparator用法示例(枚举类型排序转)
工作中遇到按照类的某个属性排列,这个属性是个枚举类型,按照要求的优先级排列. 可以使用ComparatorChain.BeanComparator.FixedOrderComparator实现. 举一 ...
- robot framework数据库操作
1.连接数据库 2.数据库查询操作 3.断开数据库连接 4.对数据库进行读取,实现登录功能实例
- Ionic 小节
教程 http://www.runoob.com/ionic/ionic-install.html 最后报错,发现是jdk版本过低,升级到8.0后正常 分析:nodejs.cordova.ionic. ...