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(孙子——爷奶)表的更多相关文章

  1. PHP表单生成器,快速生成现代化的form表单,快速上手

    form-builder PHP表单生成器,快速生成现代化的form表单.包含复选框.单选框.输入框.下拉选择框等元素以及省市区三级联动.时间选择.日期选择.颜色选择.树型.文件/图片上传等功能. 详 ...

  2. Mysql分表和分区的区别、分库分表介绍与区别

    分表和分区的区别: 一,什么是mysql分表,分区 什么是分表,从表面意思上看呢,就是把一张表分成N多个小表,具体请看:mysql分表的3种方法 什么是分区,分区呢就是把一张表的数据分成N多个区块,这 ...

  3. (喷血分享)利用.NET生成数据库表的创建脚本,类似SqlServer编写表的CREATE语句

    (喷血分享)利用.NET生成数据库表的创建脚本,类似SqlServer编写表的CREATE语句 在我们RDIFramework.NET代码生成器中,有这样一个应用,就是通过数据库表自动生成表的CREA ...

  4. sap透明表、结构、簇介绍以及查找表方法

    sap透明表.结构.簇介绍以及查找表方法 一些人在写开发功能说明书的时候不知道如何去找屏幕字段对应的透明表,下面我来介绍一个比较有效的方法:首先简单介绍一下概念:在SAP中的表的种类有以下三种:Tra ...

  5. 关于ORALCE一个表空间的数据导入到另一个表空间的方法(原创)

    用户:   whnaproject     所属表空间: whnaproject 新用户   : wniec            所属新表空间: wniec 要求:将用户whnaproject中的数 ...

  6. ylb:多表的连接与练习(第三方关联表的应用)

    ylbtech-SQL Server:SQL Server-多表的连接与练习(第三方关联表的应用) SQL Server 多表的连接与练习(第三方关联表的应用). 1,多表的连接与练习(第三方关联表的 ...

  7. 利用.NET生成数据库表的创建脚本,类似SqlServer编写表的CREATE语句

    利用.NET生成数据库表的创建脚本,类似SqlServer编写表的CREATE语句 (喷血分享)利用.NET生成数据库表的创建脚本,类似SqlServer编写表的CREATE语句 在我们RDIFram ...

  8. {MySQL的库、表的详细操作}一 库操作 二 表操作 三 行操作

    MySQL的库.表的详细操作 MySQL数据库 本节目录 一 库操作 二 表操作 三 行操作 一 库操作 1.创建数据库 1.1 语法 CREATE DATABASE 数据库名 charset utf ...

  9. Hive分区表新增字段及修改表名,列名,列注释,表注释,增加列,调整列顺序,属性名等操作

    一.Hive分区表新增字段 参考博客:https://blog.csdn.net/yeweiouyang/article/details/44851459 二.Hive修改表名,列名,列注释,表注释, ...

随机推荐

  1. js的实例方法和静态方法分析

    var Person=function(){}; Person.say=function(){ console.log('I am a Person,I can say.') }; Person.pr ...

  2. lighttpd mysql php简单教程

    lighttpd mysql php简单教程 lighttpd+php5+mysql+Debian etch lighttpd是速度最快的静态web server,mysql最通用的的database ...

  3. hdu1814(2-SAT)

    2-SAT 求出可能的解,但是这个解要是字典序最小的,所以只能采用2-SAT基本思想来解. 从小到大开始,对一个可能的点染色,染为1,然后dfs其所有能到达的点,如果其中出现一个已经标号为-1的话,那 ...

  4. md5 算法类 java

    package com.sunyard.p2p.util; import java.security.MessageDigest; import java.security.NoSuchAlgorit ...

  5. ios 时间解析 差8个小时

    啥问题也有:小程序中web开发工具里显示时间正常,ios上显示的查8小时 原因: 使用 NSDate *date = [NSDate date]; 获取的时间是标注的UTC时间,和北京时间相差8小时. ...

  6. Selenium Firefox 官方Webdriver -- Geckodriver 下载地址

    Selenium Firefox 官方Webdriver -- Geckodriver 下载地址 https://github.com/mozilla/geckodriver/releases

  7. Phonetic Symbols:2个半元音:[w] ,[j]

    2个半元音音标发音技巧与单词举例 原文地址:http://www.hlyy.in/1243.html 2个半元音音标发音技巧与半元音单词举例 [w]  发音技巧: 嘴唇张开到刚好可以含住一根吸管的程度 ...

  8. C#中对文件的操作小结

    1.建立一个文本文件 public class FileClass { public static void Main() { WriteToFile(); } static void WriteTo ...

  9. JavaScript 入门之常见对象

    常见对象 1. Object 对象 2. String 对象 3. Array 对象 4. Date 对象 5. Number 对象 6. 自定义对象 with 语句 为了简化对象调用内容的书写 格式 ...

  10. 关于oracle的sequence和trigger。

    原先mysql中每个自增字段,在oracle中就需要建立一个sequence和一个trigger. 就算同一个表中有x个自增字段,那么就需要建立x个sequence和x和trigger. 实际中,我建 ...