自定义Writable

hadoop虽然已经实现了一些非常有用的Writable,而且你可以使用他们的组合做很多事情,但是如果你想构造一些更加复杂的结果,你可以自定义Writable来达到你的目的,我们以注释的方式对自定义Writable进行讲解(不许说我只帖代码占篇幅哦,姿势写在注释里了):

  1. package com.sweetop.styhadoop;
  2. import org.apache.hadoop.io.Text;
  3. import org.apache.hadoop.io.WritableComparable;
  4. import java.io.DataInput;
  5. import java.io.DataOutput;
  6. import java.io.IOException;
  7. /**
  8. * Created with IntelliJ IDEA.
  9. * User: lastsweetop
  10. * Date: 13-7-17
  11. * Time: 下午8:50
  12. * To change this template use File | Settings | File Templates.
  13. */
  14. public class EmploeeWritable implements WritableComparable<EmploeeWritable>{
  15. private Text name;
  16. private Text role;
  17. /**
  18. * 必须有默认的构造器皿,这样Mapreduce方法才能创建对象,然后通过readFields方法从序列化的数据流中读出进行赋值
  19. */
  20. public EmploeeWritable() {
  21. set(new Text(),new Text());
  22. }
  23. public EmploeeWritable(Text name, Text role) {
  24. set(name,role);
  25. }
  26. public void set(Text name,Text role) {
  27. this.name = name;
  28. this.role = role;
  29. }
  30. public Text getName() {
  31. return name;
  32. }
  33. public Text getRole() {
  34. return role;
  35. }
  36. /**
  37. * 通过成员对象本身的write方法,序列化每一个成员对象到输出流中
  38. * @param dataOutput
  39. * @throws IOException
  40. */
  41. @Override
  42. public void write(DataOutput dataOutput) throws IOException {
  43. name.write(dataOutput);
  44. role.write(dataOutput);
  45. }
  46. /**
  47. * 同上调用成员对象本身的readFields方法,从输入流中反序列化每一个成员对象
  48. * @param dataInput
  49. * @throws IOException
  50. */
  51. @Override
  52. public void readFields(DataInput dataInput) throws IOException {
  53. name.readFields(dataInput);
  54. role.readFields(dataInput);
  55. }
  56. /**
  57. * implements WritableComparable必须要实现的方法,用于比较  排序
  58. * @param emploeeWritable
  59. * @return
  60. */
  61. @Override
  62. public int compareTo(EmploeeWritable emploeeWritable) {
  63. int cmp = name.compareTo(emploeeWritable.name);
  64. if(cmp!=0){
  65. return cmp;
  66. }
  67. return role.compareTo(emploeeWritable.role);
  68. }
  69. /**
  70. * MapReduce需要一个分割者(Partitioner)把map的输出作为输入分成一块块的喂给多个reduce)
  71. * 默认的是HashPatitioner,他是通过对象的hashcode函数进行分割,所以hashCode的好坏决定
  72. * 了分割是否均匀,他是一个很关键性的方法。
  73. * @return
  74. */
  75. @Override
  76. public int hashCode() {
  77. return name.hashCode()*163+role.hashCode();
  78. }
  79. @Override
  80. public boolean equals(Object o) {
  81. if(o instanceof EmploeeWritable){
  82. EmploeeWritable emploeeWritable=(EmploeeWritable)o;
  83. return name.equals(emploeeWritable.name) && role.equals(emploeeWritable.role);
  84. }
  85. return false;
  86. }
  87. /**
  88. * 如果你想自定义TextOutputformat作为输出格式时的输出,你需要重写toString方法
  89. * @return
  90. */
  91. @Override
  92. public String toString() {
  93. return name+"\t"+role;
  94. }
  95. }

Writable对象是可更改的而且经常被重用,因此尽量避免在write和readFields中分配对象。

自定义RawComparatorWritable

上面的EmploeeWritable已经可以跑的很溜了,但是还是有优化的空间,当作为MapReduce里的key,需要进行比较时,因为他已经被序列化,想要比较他们,那么首先要先反序列化成一个对象,然后再调用compareTo对象进行比较,但是这样效率太低了,有没有可能可以直接比较序列化后的结果呢,答案是肯定的,可以。
我们只需要把EmploeeWritable的序列化后的结果拆成成员对象,然后比较成员对象即可,那么来看代码(讲解再次写在注释里):
  1. public static class Comparator extends WritableComparator{
  2. private static final Text.Comparator TEXT_COMPARATOR= new Text.Comparator();
  3. protected Comparator() {
  4. super(EmploeeWritable.class);
  5. }
  6. @Override
  7. public int compare(byte[] b1, int s1, int l1, byte[] b2, int s2, int l2) {
  8. try {
  9. /**
  10. * name是Text类型,Text是标准的UTF-8字节流,
  11. * 由一个变长整形开头表示Text中文本所需要的长度,接下来就是文本本身的字节数组
  12. * decodeVIntSize返回变长整形的长度,readVInt表示文本字节数组的长度,加起来就是第一个成员name的长度
  13. */
  14. int nameL1= WritableUtils.decodeVIntSize(b1[s1])+readVInt(b1,s1);
  15. int nameL2=WritableUtils.decodeVIntSize(b2[s2])+readVInt(b2,s2);
  16. //和compareTo方法一样,先比较name
  17. int cmp = TEXT_COMPARATOR.compare(b1,s1,nameL1,b2,s2,nameL2);
  18. if(cmp!=0){
  19. return cmp;
  20. }
  21. //再比较role
  22. return TEXT_COMPARATOR.compare(b1,s1+nameL1,l1-nameL1,b2,s2+nameL2,l2-nameL2);
  23. } catch (IOException e) {
  24. throw new IllegalArgumentException();
  25. }
  26. }
  27. static {
  28. //注册raw comprator,更象是绑定,这样MapReduce使用EmploeeWritable时就会直接调用Comparator
  29. WritableComparator.define(EmploeeWritable.class,new Comparator());
  30. }
  31. }

我们没有直接去实现RawComparator而是继承于WritableComparator,因为WritableComparator提供了很多便捷的方法,并且对compare有个默认的实现。写compare方法时一定要小心谨慎,因为都是在字节上操作,可以好好参考下源代码里的一些Writable中Comparator的写法,另外多看下WritableUtils也是由必要的,他里面有很多简便的方法可以使用。

 

自定义comparators

有时候,除了默认的comparator,你可能还需要一些自定义的comparator来生成不同的排序队列,看一下下面这个示例,只比较name,两个compare是同一意思,都是比较name大小:
  1. public static class NameComparator extends WritableComparator{
  2. private static final Text.Comparator TEXT_COMPARATOR= new Text.Comparator();
  3. protected NameComparator() {
  4. super(EmploeeWritable.class);
  5. }
  6. @Override
  7. public int compare(byte[] b1, int s1, int l1, byte[] b2, int s2, int l2) {
  8. try {
  9. int nameL1= WritableUtils.decodeVIntSize(b1[s1])+readVInt(b1,s1);
  10. int nameL2=WritableUtils.decodeVIntSize(b2[s2])+readVInt(b2,s2);
  11. return TEXT_COMPARATOR.compare(b1,s1,nameL1,b2,s2,nameL2);
  12. } catch (IOException e) {
  13. throw new IllegalArgumentException();
  14. }
  15. }
  16. @Override
  17. public int compare(WritableComparable a, WritableComparable b) {
  18. if(a instanceof EmploeeWritable && b instanceof  EmploeeWritable){
  19. return ((EmploeeWritable)a).name.compareTo(((EmploeeWritable)b).name);
  20. }
  21. return super.compare(a,b);
  22. }
  23. }

自定义Writable、RawComparatorWritable、comparators(转)的更多相关文章

  1. 5.3.3 自定义writable和RawComparatorWritable

    5.3.3 自定义writable (1)构造员工writable Hadoop虽然已经实现了一些非常有用的Writable,而且你可以使用他们的组合做很多事情,但是如果你想构造一些更加复杂的结果,你 ...

  2. 读取SequenceFile中自定义Writable类型值

    1)hadoop允许程序员创建自定义的数据类型,如果是key则必须要继承WritableComparable,因为key要参与排序,而value只需要继承Writable就可以了.以下定义一个Doub ...

  3. Hadoop Serialization -- hadoop序列化详解 (3)【ObjectWritable,集合Writable以及自定义的Writable】

    前瞻:本文介绍ObjectWritable,集合Writable以及自定义的Writable TextPair 回顾: 前面了解到hadoop本身支持java的基本类型的序列化,并且提供相应的包装实现 ...

  4. 自定义排序及Hadoop序列化

    自定义排序 将两列数据进行排序,第一列按照升序排列,当第一列相同时,第二列升序排列. 在map和reduce阶段进行排序时,比较的是k2.v2是不参与排序比较的.如果要想让v2也进行排序,需要把k2和 ...

  5. MapReduce实例-倒排索引

    环境: Hadoop1.x,CentOS6.5,三台虚拟机搭建的模拟分布式环境 数据:任意数量.格式的文本文件(我用的四个.java代码文件) 方案目标: 根据提供的文本文件,提取出每个单词在哪个文件 ...

  6. 重新认识mapreduce

    写这篇文章,是因为最近遇到了mapreduce的二次排序问题.以前的理解不完全正确.首先看一下mapreduce的过程 相信这张图熟悉MR的人都应该见过,再来一张图 wordcount也不细说了,ha ...

  7. [大牛翻译系列]Hadoop(13)MapReduce 性能调优:优化洗牌(shuffle)和排序阶段

    6.4.3 优化洗牌(shuffle)和排序阶段 洗牌和排序阶段都很耗费资源.洗牌需要在map和reduce任务之间传输数据,会导致过大的网络消耗.排序和合并操作的消耗也是很显著的.这一节将介绍一系列 ...

  8. 一站式Hadoop&Spark云计算分布式大数据和Android&HTML5移动互联网解决方案课程(Hadoop、Spark、Android、HTML5)V2的第一门课程

    Hadoop是云计算的事实标准软件框架,是云计算理念.机制和商业化的具体实现,是整个云计算技术学习中公认的核心和最具有价值内容. 如何从企业级开发实战的角度开始,在实际企业级动手操作中深入浅出并循序渐 ...

  9. [BigData]关于Hadoop学习笔记第三天(PPT总结)(一)

     课程安排 MapReduce原理*** MapReduce执行过程** 数据类型与格式*** Writable接口与序列化机制*** ---------------------------加深拓展- ...

随机推荐

  1. Linux 性能检测 - CentOS 安装 paramon

    简介 paramon是一款性能检测工具. 数据发送:cnt 数据接收:svr Continue...

  2. iOS Node Conflict svn冲突

    当出现这个冲突时,应该是我add的文件,和同事处理的方法有冲突导致的. 这个的解决办法是:先revert这个文件,然后再update.

  3. miaov- 自动生成正V反V大于号V小于号V楼梯等图案

    1. 核心:控制 数量的长度-1-i的位置,是放在left上还是top上?是放在前面还是后面! <!DOCTYPE html> <html lang="en"&g ...

  4. SWD模式连接与注意事项

    JTAG模式与SWD模式连接图 SWD 仿真模式概念简述 一.SWD 和传统的调试方式区别 1. SWD 模式比 JTAG 在高速模式下面更加可靠. 在大数据量的情况下面 JTAG 下载程序会失败, ...

  5. Date and Time Pattern

    The following examples show how date and time patterns are interpreted in the U.S. locale. The given ...

  6. Javascript位置 body之前、后执行顺序

    简介:当页面加载的时候,嵌入html标记的js代码和位于<body></body>之间的js代码将被执行:当调用的时候,位于<head></head>之 ...

  7. Linux命令行–更多bash shell命令(转)

    4.1.1 探查程序 ps 命令 默认情况下,ps命令只会显示运行在当前控制台下的属于当前用户进程的进程 显示的当前进程的项目 进程号 运行在哪个终端(tty) 进程占用的CPU时间 Linux系统支 ...

  8. ComparatorChain、BeanComparator用法示例(枚举类型排序转)

    工作中遇到按照类的某个属性排列,这个属性是个枚举类型,按照要求的优先级排列. 可以使用ComparatorChain.BeanComparator.FixedOrderComparator实现. 举一 ...

  9. robot framework数据库操作

    1.连接数据库 2.数据库查询操作 3.断开数据库连接 4.对数据库进行读取,实现登录功能实例

  10. Ionic 小节

    教程 http://www.runoob.com/ionic/ionic-install.html 最后报错,发现是jdk版本过低,升级到8.0后正常 分析:nodejs.cordova.ionic. ...