在上一篇文章《Mapreduce实战案例(三)实现reduce端join》中,map里面我们是先把数据转化成了json,然后再转换成string,然后再把string放入到text类型里面进行向reduce传递的,如下图:
在reduce中,我们直接获取到string,再转换成json,如下图:
这样子我们不管在map还是reduce中使用的都是student对象,那么有没有可能我们map直接向reduce传递这个student对象就好,不用转来转去的。答案是有可能,就是需要自己实现这里的writable。下面我们直接来实操下:
1)我们把studentpojo改造下,之前实现的是Serializable序列化,这里的话我们修改成Writable实例化即可,如下图:
既然实现了这个序列化的话,我们就要实现这里的序列化和反序列化的方法:
public void write(DataOutput out) throws IOException { LOGGER.info("准备写入的数据是:{}", this.toString()); // int类型使用writeInt if (null != student_id) { out.writeInt(student_id); } else { out.writeInt(-1); } if (null != school_id) { out.writeInt(school_id); } else { out.writeInt(-1); } // string类型使用writeUTF if (StringUtils.isNotBlank(student_name)) { out.writeUTF(student_name); } else { out.writeUTF(""); } if (StringUtils.isNotBlank(school_name)) { out.writeUTF(school_name); } else { out.writeUTF(""); } if (StringUtils.isNotBlank(school_address)) { out.writeUTF(school_address); } else { out.writeUTF(""); } } public void readFields(DataInput in) throws IOException { // int类型使用readInt student_id = in.readInt(); school_id = in.readInt(); // string类型使用writeUTF student_name = in.readUTF(); school_name = in.readUTF(); school_address = in.readUTF(); }
备注:
1、这里的话我们的输入和输出数量要保持一致,即使某些字段为空也需要有一个占位符,不然在读取的时候读取不到。
2、这里我们使用了Writable序列化就不要再添加Serializable序列化了。
2)修改mapper,把出类型修改为这里的StudentPoJo2,示例图如下:
然后我们在map里面使用context直接写studentpojo对象即可,如下图:
3)修改reducer的读取,把输入类型修改为studentpojo,如下图:
然后在reduce里面我们直接获取这个studentpojo对象即可:
然后我们这里把job名称设置为2:
然后我们把项目打包上传到服务器上运行下看看:
可以看到完全没问题。最后附上本案例的源码,登录后即可下载:
还没有评论,来说两句吧...