MapReduce功能实现十一---join

MapReduce功能实现系列
      MapReduce功能实现一—Hbase和Hdfs之间数据相互转换
      MapReduce功能实现二—排序
      MapReduce功能实现三—Top N
      MapReduce功能实现四—小综合(从hbase中读取数据统计并在hdfs中降序输出Top 3)
      MapReduce功能实现五—去重(Distinct)、计数(Count)
      MapReduce功能实现六—最大值(Max)、求和(Sum)、平均值(Avg)
      MapReduce功能实现七—小综合(多个job串行处理计算平均值)
      MapReduce功能实现八—分区(Partition)
      MapReduce功能实现九—Pv、Uv
      MapReduce功能实现十—倒排索引(Inverted Index)
      MapReduce功能实现十一—join
 

1.前言:

  对两份数据data1和data2进行关键词连接是一个很通用的问题,在关系型数据库中Join是非常常见的操作,各种优化手段已经到了极致。在海量数据的环境下,不可避免的也会碰到这种类型的需求,例如在数据分析时需要从不同的数据源中获取数据。不同于传统的单机模式,在分布式存储下采用MapReduce编程模型,也有相应的处理措施和优化方法。
 

2.模拟数据:
[hadoop@h71 q1]$ vi mz.txt
zs 1
ls 2
ww 3
zl 2
qq 2
hh 1
[hadoop@h71 q1]$ vi jg.txt
1 beijing
2 tianjing
3 shanghai
3.将数据上传到hdfs上:
[hadoop@h71 q1]$ hadoop fs -mkdir /user/hadoop/m_in

[hadoop@h71 q1]$ hadoop fs -put mz.txt /user/hadoop/m_in
[hadoop@h71 q1]$ hadoop fs -put jg.txt /user/hadoop/m_in
4.Java代码:

[hadoop@h71 q1]$ vi MTjoin.java

import java.io.IOException;
import java.util.Iterator;
import java.util.StringTokenizer;
 
import org.apache.hadoop.conf.Configuration;
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;
import org.apache.hadoop.util.GenericOptionsParser;
 
public class MTjoin {
 
    public static int time = 0;
    /*
     * 在map中先区分输入行属于左表还是右表,然后对两列值进行分割,
     * 保存连接列在key值,剩余列和左右表标志在value中,最后输出
     */
    public static class Map extends Mapper<Object, Text, Text, Text> {
        // 实现map函数
        public void map(Object key, Text value, Context context) throws IOException, InterruptedException {
            String line = value.toString();// 每行文件
            String relationtype = new String();// 左右表标识
            // 输入文件首行,不处理
            if (line.contains("name") == true || line.contains("addressed") == true) {
                return;
            }
            // 输入的一行预处理文本
            StringTokenizer itr = new StringTokenizer(line);
            String mapkey = new String();
            String mapvalue = new String();
            int i = 0;
            while (itr.hasMoreTokens()) {
                // 先读取一个单词
                String token = itr.nextToken();
                // 判断该地址ID就把存到"values[0]"
                //charAt() 方法可返回指定位置的字符
                if (token.charAt(0) >= '0' && token.charAt(0) <= '9') {
                    mapkey = token;
                    if (i > 0) {
                        relationtype = "1";
                    } else {
                        relationtype = "2";
                    }
                    //break的作用是跳出当前循环块,continue用于结束循环体中其后语句的执行
                    continue;
                }
                // 存工厂名
                mapvalue += token + " ";
                i++;
            }
            // 输出左右表
            context.write(new Text(mapkey), new Text(relationtype + "+"+ mapvalue));
        }
    }
    /*
     * reduce解析map输出,将value中数据按照左右表分别保存,
  	 * 然后求出笛卡尔积,并输出。
     */
    public static class Reduce extends Reducer<Text, Text, Text, Text> {
        // 实现reduce函数
        public void reduce(Text key, Iterable<Text> values, Context context) throws IOException, InterruptedException {
            // 输出表头
            if (0 == time) {
                context.write(new Text("name"), new Text("address"));
                time++;
            }
            int factorynum = 0;
            String[] factory = new String[10];
            int addressnum = 0;
            String[] address = new String[10];
            Iterator ite = values.iterator();
            while (ite.hasNext()) {
                String record = ite.next().toString();
                int len = record.length();
                int i = 2;
                if (0 == len) {
                    continue;
                }
                // 取得左右表标识
                char relationtype = record.charAt(0);
                // 左表
                if ('1' == relationtype) {
                    factory[factorynum] = record.substring(i);
                    factorynum++;
                }
                // 右表
                if ('2' == relationtype) {
                    address[addressnum] = record.substring(i);
                    addressnum++;
                }
            }
            // 求笛卡尔积
            if (0 != factorynum && 0 != addressnum) {
                for (int m = 0; m < factorynum; m++) {
                    for (int n = 0; n < addressnum; n++) {
                        // 输出结果
                        context.write(new Text(factory[m]),
                                new Text(address[n]));
                    }
                }
            }
        }
    }
 
    public static void main(String[] args) throws Exception {
        Configuration conf = new Configuration();
        // 这句话很关键
        conf.set("mapred.jar", "mt.jar");
        String[] ioArgs = new String[] { "m_in", "m_out" };
        String[] otherArgs = new GenericOptionsParser(conf, ioArgs).getRemainingArgs();
        if (otherArgs.length != 2) {
            System.err.println("Usage: Multiple Table Join <in> <out>");
            System.exit(2);
        }
        Job job = new Job(conf, "Multiple Table Join");
        job.setJarByClass(MTjoin.class);
 
        // 设置Map和Reduce处理类
        job.setMapperClass(Map.class);
        job.setReducerClass(Reduce.class);
 
        // 设置输出类型
        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(Text.class);
 
        // 设置输入和输出目录
        FileInputFormat.addInputPath(job, new Path(otherArgs[0]));
        FileOutputFormat.setOutputPath(job, new Path(otherArgs[1]));
        System.exit(job.waitForCompletion(true) ? 0 : 1);
    }
}
5.执行:
[hadoop@h71 q1]$ /usr/jdk1.7.0_25/bin/javac MTjoin.java
[hadoop@h71 q1]$ /usr/jdk1.7.0_25/bin/jar cvf xx.jar MTjoin*class
[hadoop@h71 q1]$ hadoop jar xx.jar MTjoin
6.查看结果:
[hadoop@h71 q1]$ hadoop fs -cat /user/hadoop/m_out/part-r-00000
name    address
hh      beijing
zs      beijing
qq      tianjing
zl      tianjing
ls      tianjing
ww      shanghai
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小强签名设计

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值