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. ChemDraw的“键”工具的作用是什么

    ChemDraw的“键”工具在化学研究中能够发挥重大作用,如果你也是一名化学相关工作者就千万不要错过这篇教程,下文详细盘点“键”工具究竟能干些什么. ChemDraw化学软件免费获取地址:http:/ ...

  2. Python 构造函数、 Python 析构函数、Python 垃圾回收机制

    构造函数与析构函数 构造函数: 用于初始化类的内容部状态,Python提供的构造函数式 __init__(); 也就是当该类被实例化的时候就会执行该函数.那么我们就可以把要先初始化的属性放到这个函数里 ...

  3. Java Tomcat7性能监控与优化详解

    1.   目的 通过优化tomcat提高网站的并发能力. 2.   服务器资源 服务器所能提供CPU.内存.硬盘的性能对处理能力有决定性影响. 3.   优化配置 3.1. 配置tomcat管理员账户 ...

  4. Yolo+Windows 配置(详细版)

    一.配置环境  VS2013+显卡GtX1080ti+CUDA7.5+Opencv3.1.0+pthread pthread:ftp://sourceware.org/pub/pthreads-win ...

  5. 《从零开始学Swift》学习笔记(Day 63)——Cocoa Touch设计模式及应用之单例模式

    原创文章,欢迎转载.转载请注明:关东升的博客 什么是设计模式.设计模式是在特定场景下对特定问题的解决方案,这些解决方案是经过反复论证和测试总结出来的.实际上,除了软件设计,设计模式也被广泛应用于其他领 ...

  6. [LintCode] A + B 问题

    Bit-by-Bit summation: class Solution { public: /* * @param a: The first integer * @param b: The seco ...

  7. ChannelOption用到的socket的标准参数

    ChannelOption.SO_BACKLOG, 1024 BACKLOG用于构造服务端套接字ServerSocket对象,标识当服务器请求处理线程全满时,用于临时存放已完成三次握手的请求的队列的最 ...

  8. 巨蟒python全栈开发-第23天 内置常用模块2

    一.今日主要内容 1.nametuple:(命名元组,本质还是元组) 命名元组=>类似创建了一个类 结构化时间其实是个命名元组 2.os 主要是针对操作系统的 一般用来操作文件系统 os.mak ...

  9. Oracle http://127.0.0.1:8080/apex无法访问解决方案

    造成无法访问的原因多数情况是由于Oracle中TNS的配置发生了改变. 造成TNS配置有问题的原因可能是:1. 修改了计算机名    2. 修改了IP 默认oracleXE 启动OracleXETNS ...

  10. 关于ajax里边不能识别$(this)的解决方法

    在ajax外面弄个变量var mythis = $(this),然后在里面用就行