一、 为什么javaBean要继承Writable和WritableComparable接口?

1. 如果一个javaBean想要作为MapReduce的key或者value,就一定要实现序列化,因为在Map到Reduce阶段的时候,只能是传输二进制数据,不可能将字符流直接进行RPC传输,

只要一个javabean实现了序列化和反序列化,就可以做为key或者value

最简单的序列化和反序列化就是实现Writable接口

ps:javaBean在作为key的时候有点不同,除了要继承Writable接口还需要实现Comparable接口

因为在shuffle到Reduce阶段的合并阶段,需要根据key对数据进行排序,合并,如果不实现这个接口,运行时会出错

WritableComparable就是Writable接口和java.lang.Comparable<T>的一个子接口,所以将要作为key的javaBean直接继承WritableComparable就可以了

2. java序列化与Writable序列化的比较

2.1 java序列化不够灵活,为了更好的控制序列化的整个流程所以使用Writable

2.2 java序列化不符合序列化的标准,没有做一定的压缩,java序列化首先写类名,然后再是整个类的数据,而且成员对象在序列化中只存引用,成员对象的可以出现的位置很随机,既可以在序列化的对象前,也可以在其后面,这样就对随机访问造成影响,一旦出错,整个后面的序列化就会全部错误

2.3 Java序列化每次序列化都要重新创建对象,内存消耗大,而Writable是可以重用的

二、 实现Writable和WritableComparable的UserBean

代码如下:

package com.qjx.serialize_8_2;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException; import org.apache.hadoop.io.WritableComparable; public class UserBean implements WritableComparable<UserBean> { private int id;
private String name ;
private String age; public UserBean() {
} public UserBean(int id,String name , String age) {
this.id = id;
this.name = name;
this.age = age;
} @Override
public String toString() {
return this.id + this.name + this.age;
} //反序列化,将输入二进制反序列化为字符流
@Override
public void readFields(DataInput in) throws IOException {
id = in.readInt();
name = in.readUTF();
age = in.readUTF();
} //序列化,将字节转化为二进制输出
@Override
public void write(DataOutput out) throws IOException {
out.writeInt(id);
out.writeUTF(name);
out.writeUTF(age);
} @Override
public int compareTo(UserBean o) {
int thisValue = this.id;
int thatValue = o.id;
return (thisValue < thatValue ? -1 : (thisValue==thatValue ? 0 : 1));
} public int getId() {
return id;
} public void setId(int id) {
this.id = id;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public String getAge() {
return age;
} public void setAge(String age) {
this.age = age;
}
}

三、 MapReduce传递UserBean的一个简单例子

我们已经实现了可序列化的UserBean类,现在就做一个简单的例子,在MapReduce中传递UserBean

1. 准备一个文件user.txt,内容如下:

1 'tom' '22',2 'tom2' '22',3 'tom3' '22',4 'tom4' '22',5 'tom5' '22',6 'tom6' '22',7 'tom7' '22',8 'tom8' '22',9 'tom9' '22',10 'tom10' '22',11 'tom11' '22',12 'tom12' '22',13 'tom13' '22',1 'tom' '22',1 'tom' '22',2 'tom2' '22',2 'tom2' '22',

这个文件中有多个UserBean,我们的MapReduce就是要实现统计这些UserBean出现的次数

2. WCMapper.java的实现代码:

package com.qjx.serialize_8_2;

import java.io.IOException;

import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper; /*
* Writable接口是一个实现了序列化协议的序列化对象。
* 在Hadoop中定义一个结构化对象都要实现Writable接口,使得该结构化对象可以序列化为字节流,字节流也可以反序列化为结构化对象。
* LongWritable类型:Hadoop.io对Long类型的封装类型
*/ public class WCMapper extends Mapper<LongWritable, Text, UserBean, LongWritable>{ @Override
protected void map(LongWritable key, Text value, Mapper<LongWritable, Text, UserBean, LongWritable>.Context context)
throws IOException, InterruptedException { // 获得每行文档内容,并且进行折分
String[] users = value.toString().split(","); // 遍历折份的内容
System.out.println(users.length);
for (String u1 : users) {
//根据空格划分为三个属性
String[] u = u1.toString().split(" ");
System.out.println(u.length);
if(u!=null && u.length== 3) {
UserBean u2 = new UserBean(Integer.parseInt(u[0]),u[1],u[2]);
context.write(u2, new LongWritable(1));
}
else {
System.out.println("user split false !");
}
}
}
}

3. WCReducer.java实现代码:

package com.qjx.serialize_8_2;

import java.io.IOException;

import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer; import com.qjx.serialize_8_2.UserBean; public class WCReducer extends Reducer<UserBean, LongWritable, UserBean, LongWritable>{ @Override
protected void reduce(UserBean key, Iterable<LongWritable> values,
Reducer<UserBean, LongWritable, UserBean, LongWritable>.Context context) throws IOException, InterruptedException { long sum = 0;
for (LongWritable i : values) {
// i.get转换成long类型
sum += i.get();
}
// 输出总计结果
context.write(key, new LongWritable(sum));
}
}

4. UserCount.java 的实现代码:

package com.qjx.serialize_8_2;

import java.io.IOException;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat; public class UserCount { public static void main(String[] args) throws ClassNotFoundException, IOException, InterruptedException {
// 创建job对象
Job job = Job.getInstance(new Configuration());
// 指定程序的入口
job.setJarByClass(UserCount.class); // 指定自定义的Mapper阶段的任务处理类
job.setMapperClass(WCMapper.class);
job.setMapOutputKeyClass(UserBean.class);
job.setMapOutputValueClass(LongWritable.class);
// 本地数据的输入路径
FileInputFormat.setInputPaths(job, new Path("E:/trainingPack/serialize/input")); // 指定自定义的Reducer阶段的任务处理类
job.setReducerClass(WCReducer.class);
// 设置最后输出结果的Key和Value的类型 x
job.setOutputKeyClass(UserBean.class);
job.setOutputValueClass(LongWritable.class);
// 将计算的结果存到本地
FileOutputFormat.setOutputPath(job, new Path("E:/trainingPack/serialize/output")); // 执行提交job方法,直到完成,参数true打印进度和详情
job.waitForCompletion(true);
System.out.println("Finished");
}
}

5. 执行结果,生成的output内容如下:

1'tom''22'    3
2'tom2''22' 3
3'tom3''22' 1
4'tom4''22' 1
5'tom5''22' 1
6'tom6''22' 1
7'tom7''22' 1
8'tom8''22' 1
9'tom9''22' 1
10'tom10''22' 1
11'tom11''22' 1
12'tom12''22' 1
13'tom13''22' 1

hadoop学习第四天-Writable和WritableComparable序列化接口的使用&&MapReduce中传递javaBean的简单例子的更多相关文章

  1. Hadoop学习笔记四

    一.fsimage,edits和datanode的block在本地文件系统中位置的配置 fsimage:hdfs-site.xml中的dfs.namenode.name.dir  值例如file:// ...

  2. 第四周之Hadoop学习(四)

    上周已经成功完成了Hadoop的学习,这周则是搭建好Hadoop的安卓编程环境 今天的学习根据这篇博客:https://blog.csdn.net/HcJsJqJSSM/article/details ...

  3. hadoop 学习(四)之java操作hdfs

    1.导入hadoop jar包 将hadoop/share/common/目录.hadoop/share/common/lib/目录.hadoop/hdfs/目录.下的jar包加入eclipse. 2 ...

  4. Hadoop学习(四) FileSystem Shell命令详解

    FileSystem Shell中大多数命令都和unix命令相同,只是两者之间的解释不同,如果你对unix命令有基本的了解,那么对于FileSystem Shell的命令,你将会感到很亲切. appe ...

  5. hadoop学习笔记(四)——eclipse+maven+hadoop2.5.2源代码

    Eclipse同maven进口hadoop源代码 1)  安装和配置maven环境变量 M2_HOME: D:\profession\hadoop\apache-maven-3.3.3 PATH: % ...

  6. Hadoop-wordCount实例代码编写(Hadoop学习第四天)

    1.新建一个maven项目2.pom文件中引入以下jar包<dependency> <groupId>org.apache.hadoop</groupId> < ...

  7. 【Java学习笔记之二十二】解析接口在Java继承中的用法及实例分析

    一.定义 Java接口(Interface),是一系列方法的声明,是一些方法特征的集合,一个接口只有方法的特征没有方法的实现,因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为( ...

  8. Java学习——方法中传递参数分简单类型与复杂类型(引用类型)编程计算100+98+96+。。。+4+2+1的值,用递归方法实现

    package hello; public class digui { public static void main(String[] args) { // TODO Auto-generated ...

  9. 大二暑假第五周总结--开始学习Hadoop基础(四)

    简单学习MapReduce并进行WordCount实践 分布式并行编程: MapReduce设计的一个理念就是“计算向数据靠拢”,将复杂的,运行于大规模集群上的并行计算过程高度地抽象到两个函数:Map ...

随机推荐

  1. 一步步教你如何进行Xilinx SerDes调试

    FPGA SERDES的应用需要考虑到板级硬件,SERDES参数和使用,应用协议等方面.由于这种复杂性,SERDES的调试工作对很多工程师来说是一个挑战.本文将描述SERDES的一般调试方法,便于工程 ...

  2. web info

    http://blog.csdn.net/qq_24473141/article/details/51363662 http://blog.sina.com.cn/s/blog_8e392fc2010 ...

  3. Spring的AOP配置

    Spring的AOP配置 1.先写一个普通类: package com.spring.aop; public class Common {  public void execute(String us ...

  4. GCD - Extreme (II) for(i=1;i<N;i++) for(j=i+1;j<=N;j++) { G+=gcd(i,j); } 推导分析+欧拉函数

    /** 题目:GCD - Extreme (II) 链接:https://vjudge.net/contest/154246#problem/O 题意: for(i=1;i<N;i++) for ...

  5. 【转】【Mac系统】之ADB命令总结

    参考文章: 张明云:<Android ADB命令大全(通过ADB命令查看wifi密码.MAC地址.设备信息.操作文件.查看文件.日志信息.卸载.启动和安装APK等)> Yjnull:< ...

  6. 对Servlet容器的补充和一个问题的请教

    [0]README 0.1)本文是对 一个servlet容器  的补充: 0.2)发这个博文的最终目的是为了请教各位前辈,帮我解决一个问题,问题描述在文末, 谢谢: [1]Servlet容器 1.1) ...

  7. php+redis秒杀

    啥都不说了,看代码 前台: 包括开始和结束的秒杀时间,倒计时插件,统一看一遍再去写代码,思路会更清晰. js文件引入一个.min.js和一个插件js(在下面,自己复制吧) // JavaScript ...

  8. Android-ViewPagerIndicator框架使用——Circle

    前言:Circle适用于应用新功能的展示页和商品的多张图片的展示功能. 1.定义布局文件:SampleCirclesDefault中添加了一个布局:simple_circles. 布局中定义一个Lin ...

  9. ios 集成阿里百川的坑-【SDK初始化-iOS】读取身份图片AppKey失败

    最简易方法调用淘宝app: 引用文件 #import <AlibcTradeSDK/AlibcTradeSDK.h> AlibcWebViewController* view = [[Al ...

  10. Laragon集成开发环境+配置Xdebug+postman运行Xdebug

    [ Laravel 5.5 文档 ] 快速入门 —— 使用 Laragon 在 Windows 中搭建 Laravel 开发环境:http://laravelacademy.org/post/7754 ...