MapReduce:给出children-parents(孩子——父母)表,要求输出grandchild-grandparent(孙子——爷奶)表
hadoop中使用MapReduce单表关联案例:
MapReduce:给出children-parents(孩子——父母)表,要求输出grandchild-grandparent(孙子——爷奶)表。
给出表:
Tom Lucy
Tom Jack
Jone Lucy
Jone Jack
Lucy Mary
Lucy Ben
Jack Alice
Jack Jesse
Terry Alice
Terry Jesse
Philip Terry
Philip Alma
Mark Terry
Mark Alma
要求实现如下效果:

设计思路:将这张单表分成两张表如下:

将左表的parents列和右表的child列进行连接,连接结果中除去连接的两列就是所需要的结果:"grandchild--grandparents"表。
因为MapReduce的shuffle过程会将相同的key会连接在一起,所以在map阶段将读入数据分割成children和parents之后,
左表:将parents设置成key,children设置成value进行输出
右表:将children设置成key,parents设置成value进行输出
为了区分输出中的左右表,需要在输出的value中再加上左右表的信息,比如在value的最开始处加上字符1表示左表,加上字符2表示右表。
这样在map的结果中就形成了左表和右表,然后在shuffle过程中完成连接。
reduce接收到连接的结果,遍历values集合,得到每个value的值,将左表中的children放入children数组,右表中的parents放入parents数组,然后对两个数组求笛卡尔积就能得到最后结果。
代码如下(由于水平有限,不保证完全正确,如果发现错误欢迎指正):
package com; import java.io.IOException;
import java.util.ArrayList;
import java.util.List; import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat; public class TestParents {
public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
Configuration config = new Configuration();
config.set("fs.defaultFS", "hdfs://192.168.0.100:9000");
config.set("yarn.resourcemanager.hostname", "192.168.0.100"); FileSystem fs = FileSystem.get(config); Job job = Job.getInstance(config); job.setJarByClass(TestParents.class); //设置所用到的map类
job.setMapperClass(myMapper.class);
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(Text.class); //设置用到的reducer类
job.setReducerClass(myReducer.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(Text.class); //设置输入输出地址
FileInputFormat.addInputPath(job, new Path("/input/parent.txt")); Path path = new Path("/output3/"); if(fs.exists(path)){
fs.delete(path, true);
} //指定文件的输出地址
FileOutputFormat.setOutputPath(job, path); //启动处理任务job
boolean completion = job.waitForCompletion(true);
if(completion){
System.out.println("Job Success!");
} } public static class myMapper extends Mapper<Object, Text, Text, Text> {
// 实现map函数
public void map(Object key, Text value, Context context) throws IOException, InterruptedException {
String temp=new String();// 左右表标识 String values=value.toString();
String words[]=values.split(" "); //Tom Lucy
// 输出左表
temp = "";
context.write(new Text(words[]), new Text(temp +"+"+ words[] + "+" + words[]));
//(Lucy,1+Tom+Lucy) // 输出右表
temp = "";
context.write(new Text(words[]), new Text(temp +"+"+ words[] + "+" + words[]));
//(Tom,2+Tom+Lucy)
}
} public static class myReducer extends Reducer<Text, Text, Text, Text> {
// 实现reducer函数
public void reduce(Text key, Iterable<Text> values, Context context) throws IOException, InterruptedException {
List<String> grandchild = new ArrayList<String>();
List<String> grandparent = new ArrayList<String>(); for (Text value : values) {
char temp=(char) value.charAt();
String words[]=value.toString().split("[+]"); //1,Tom+Lucy
// +、*、|、/等符号在正则表达示中有相应的不同意义,一般来讲只需要加[]、或是\\即可 if(temp == ''){
grandchild.add(words[]);
} if(temp == ''){
grandparent.add(words[]);
}
} //求笛卡尔儿积
for (String gc : grandchild) {
for (String gp : grandparent) {
context.write(new Text(gc),new Text(gp));
}
}
}
}
}
运行详解:
(1)Map处理如下所示:
Tom Lucy map输出: <Lucy,+Tom+Lucy>
<Tom,+Tom+Lucy > Tom Jack map输出: <Jack,+Tom+Jack>
<Tom,+Tom+Jack> Jone Lucy map输出: <Lucy,+Jone+Lucy>
<Jone,+Jone+Lucy> Jone Jack map输出: <Jack,+Jone+Jack>
<Jone,+Jone+Jack> Lucy Mary map输出: <Mary,+Lucy+Mary>
<Lucy,+Lucy+Mary> Lucy Ben map输出: <Ben,+Lucy+Ben>
<Lucy,+Lucy+Ben> Jack Alice map输出: <Alice,+Jack+Alice>
<Jack,+Jack+Alice> Jack Jesse map输出: <Jesse,+Jack+Jesse>
<Jack,+Jack+Jesse> Terry Alice map输出: <Alice,+Terry+Alice>
<Terry,+Terry+Alice> Terry Jesse map输出: <Jesse,+Terry+Jesse>
<Terry,+Terry+Jesse> Philip Terry map输出: <Terry,+Philip+Terry>
<Philip,+Philip+Terry> Philip Alma map输出: <Alma,+Philip+Alma>
<Philip,+Philip+Alma> Mark Terry map输出: <Terry,+Mark+Terry>
<Mark,+Mark+Terry> Mark Alma map输出: <Alma,+Mark+Alma>
<Mark,+Mark+Alma>
(2)Shuffle处理如下:
|
map函数输出 |
排序结果 |
shuffle连接 |
|
<Lucy,1+Tom+Lucy> <Tom,2+Tom+Lucy> <Jack,1+Tom+Jack> <Tom,2+Tom+Jack> <Lucy,1+Jone+Lucy> <Jone,2+Jone+Lucy> <Jack,1+Jone+Jack> <Jone,2+Jone+Jack> <Mary,1+Lucy+Mary> <Lucy,2+Lucy+Mary> <Ben,1+Lucy+Ben> <Lucy,2+Lucy+Ben> <Alice,1+Jack+Alice> <Jack,2+Jack+Alice> <Jesse,1+Jack+Jesse> <Jack,2+Jack+Jesse> <Alice,1+Terry+Alice> <Terry,2+Terry+Alice> <Jesse,1+Terry+Jesse> <Terry,2+Terry+Jesse> <Terry,1+Philip+Terry> <Philip,2+Philip+Terry> <Alma,1+Philip+Alma> <Philip,2+Philip+Alma> <Terry,1+Mark+Terry> <Mark,2+Mark+Terry> <Alma,1+Mark+Alma> <Mark,2+Mark+Alma> |
<Alice,1+Jack+Alice> <Alice,1+Terry+Alice> <Alma,1+Philip+Alma> <Alma,1+Mark+Alma> <Ben,1+Lucy+Ben> <Jack,1+Tom+Jack> <Jack,1+Jone+Jack> <Jack,2+Jack+Alice> <Jack,2+Jack+Jesse> <Jesse,1+Jack+Jesse> <Jesse,1+Terry+Jesse> <Jone,2+Jone+Lucy> <Jone,2+Jone+Jack> <Lucy,1+Tom+Lucy> <Lucy,1+Jone+Lucy> <Lucy,2+Lucy+Mary> <Lucy,2+Lucy+Ben> <Mary,1+Lucy+Mary> <Mark,2+Mark+Terry> <Mark,2+Mark+Alma> <Philip,2+Philip+Terry> <Philip,2+Philip+Alma> <Terry,2+Terry+Alice> <Terry,2+Terry+Jesse> <Terry,1+Philip+Terry> <Terry,1+Mark+Terry> <Tom,2+Tom+Lucy> <Tom,2+Tom+Jack> |
<Alice,1+Jack+Alice, 1+Terry+Alice , 1+Philip+Alma, 1+Mark+Alma > <Ben,1+Lucy+Ben> <Jack,1+Tom+Jack, 1+Jone+Jack, 2+Jack+Alice, 2+Jack+Jesse > <Jesse,1+Jack+Jesse, 1+Terry+Jesse > <Jone,2+Jone+Lucy, 2+Jone+Jack> <Lucy,1+Tom+Lucy, 1+Jone+Lucy, 2+Lucy+Mary, 2+Lucy+Ben> <Mary,1+Lucy+Mary, 2+Mark+Terry, 2+Mark+Alma> <Philip,2+Philip+Terry, 2+Philip+Alma> <Terry,2+Terry+Alice, 2+Terry+Jesse, 1+Philip+Terry, 1+Mark+Terry> <Tom,2+Tom+Lucy, 2+Tom+Jack> |
(3)Reduce处理:
取出values(Jack , {1+Tom+Jack},{1+Jone+Jack},{1+Jone+Jack},{2+Jack+Jesse })遍历出来的一条value的值:1+Tom+Jack
根据1或者2,把值给grandchild数组和grandparent数组。
最后由语句: for (String gc : grandchild) {
for (String gp : grandparent) {
context.write(new Text(gc),new Text(gp));
}
}
得知:只要数组grandchild中没有值或者数组grandparent没有值,则不会做处理,根据这条规则去除无效的shuffle连接,就能得出最后的结果。
如果您认为这篇文章还不错或者有所收获,您可以通过右边的“打赏”功能 打赏我一杯咖啡【物质支持】,也可以点击下方的【好文要顶】按钮【精神支持】,因为这两种支持都是使我继续写作、分享的最大动力!
MapReduce:给出children-parents(孩子——父母)表,要求输出grandchild-grandparent(孙子——爷奶)表的更多相关文章
- PHP表单生成器,快速生成现代化的form表单,快速上手
form-builder PHP表单生成器,快速生成现代化的form表单.包含复选框.单选框.输入框.下拉选择框等元素以及省市区三级联动.时间选择.日期选择.颜色选择.树型.文件/图片上传等功能. 详 ...
- Mysql分表和分区的区别、分库分表介绍与区别
分表和分区的区别: 一,什么是mysql分表,分区 什么是分表,从表面意思上看呢,就是把一张表分成N多个小表,具体请看:mysql分表的3种方法 什么是分区,分区呢就是把一张表的数据分成N多个区块,这 ...
- (喷血分享)利用.NET生成数据库表的创建脚本,类似SqlServer编写表的CREATE语句
(喷血分享)利用.NET生成数据库表的创建脚本,类似SqlServer编写表的CREATE语句 在我们RDIFramework.NET代码生成器中,有这样一个应用,就是通过数据库表自动生成表的CREA ...
- sap透明表、结构、簇介绍以及查找表方法
sap透明表.结构.簇介绍以及查找表方法 一些人在写开发功能说明书的时候不知道如何去找屏幕字段对应的透明表,下面我来介绍一个比较有效的方法:首先简单介绍一下概念:在SAP中的表的种类有以下三种:Tra ...
- 关于ORALCE一个表空间的数据导入到另一个表空间的方法(原创)
用户: whnaproject 所属表空间: whnaproject 新用户 : wniec 所属新表空间: wniec 要求:将用户whnaproject中的数 ...
- ylb:多表的连接与练习(第三方关联表的应用)
ylbtech-SQL Server:SQL Server-多表的连接与练习(第三方关联表的应用) SQL Server 多表的连接与练习(第三方关联表的应用). 1,多表的连接与练习(第三方关联表的 ...
- 利用.NET生成数据库表的创建脚本,类似SqlServer编写表的CREATE语句
利用.NET生成数据库表的创建脚本,类似SqlServer编写表的CREATE语句 (喷血分享)利用.NET生成数据库表的创建脚本,类似SqlServer编写表的CREATE语句 在我们RDIFram ...
- {MySQL的库、表的详细操作}一 库操作 二 表操作 三 行操作
MySQL的库.表的详细操作 MySQL数据库 本节目录 一 库操作 二 表操作 三 行操作 一 库操作 1.创建数据库 1.1 语法 CREATE DATABASE 数据库名 charset utf ...
- Hive分区表新增字段及修改表名,列名,列注释,表注释,增加列,调整列顺序,属性名等操作
一.Hive分区表新增字段 参考博客:https://blog.csdn.net/yeweiouyang/article/details/44851459 二.Hive修改表名,列名,列注释,表注释, ...
随机推荐
- 设置label中的对齐方式
QLabel.setAlignment (self, Qt.Alignment) 下面查看Qt.Alignment: Qt.AlignmentFlag This enum type is used t ...
- C语言程序设计-同一天生日[综合应用]
[问题描述] 在一个有200人的大班级中,存在两个人生日相同的概率非常大,现给出每个学生的学号,出生月日,试找出所有生日相同的学生. [输入形式] 第一行为整数n,表示有n个学生,n<=200. ...
- spring boot打包会有.war.original文件的原因 (笔记)
今天使用spring boot 2.1.1.RELEASE版本搭建项目,虽然可以直接打包成可运行的jar包,但是由于公司准备采用docker容器来管理项目,所以需要把jar包变成war包,并且war包 ...
- 【BZOJ4584】[Apio2016]赛艇 DP
[BZOJ4584][Apio2016]赛艇 Description 在首尔城中,汉江横贯东西.在汉江的北岸,从西向东星星点点地分布着个划艇学校,编号依次为到.每个学校都拥有若干艘划艇.同一所学校的所 ...
- 【BZOJ1822】[JSOI2010]Frozen Nova 冷冻波 几何+二分+网络流
[BZOJ1822][JSOI2010]Frozen Nova 冷冻波 Description WJJ喜欢“魔兽争霸”这个游戏.在游戏中,巫妖是一种强大的英雄,它的技能Frozen Nova每次可以杀 ...
- 支付宝app支付提示 系统繁忙,请稍后重试
v2版本的支付宝支付,无论怎么调试返回的都是系统繁忙,请稍后重试提示.经过对给的示例代码的仔细研究,最后发现是由于老版本的sign_type 不加入签名计算,而新版本的支付签名它是加入签名计算的.供大 ...
- float元素一定要闭合
float:left; float:right; 一定要两个元素一起放float
- python之设置小数保留位数
python之设置小数保留位数 test.py: a = [3,4,4,4,6,4] average1 = float(sum(a)/len(a)) average2 =round(average1, ...
- Vulnerabilities by Type
w http://hackergossips.com/cross-site-scriptingxss-and-preventing/
- Python glob使用
http://www.cnblogs.com/lovemo1314/archive/2011/04/26/2029556.html 说明: glob是python自己带的一个文件操作相关模块,用它可以 ...