结合案例讲解MapReduce重要知识点 ------- 两个表的简单join操作

待处理数据 内容如下

表1:
 child	parent
 张三	王阿姨
 张三	张大叔
 张张	王阿姨
 张张	张大叔
 王阿姨 王奶奶
 王阿姨 王大爷
 张大叔 张奶奶
 张大叔 张大爷

处理后的数据 内容如下

输出数据:
grandchild grandparent
 *张三	张大爷
 *张三	张奶奶
 *张三	王奶奶
 *张三	王大爷
 *张张	张大爷
 *张张	张奶奶
 *张张	王奶奶
 *张张	王大爷
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.LongWritable;
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.Reducer.Context;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.util.GenericOptionsParser;
import org.apache.hadoop.util.Tool;
import org.apache.hadoop.util.ToolRunner;

/**
 * 
 * @author lyd
 *
 *数据:
 *
 *表:
 *child parent
 *张三 王阿姨
 *张三 张大叔
 *张张 王阿姨
 *张张 张大叔
 *王阿姨 王奶奶
 *王阿姨 王大爷
 *张大叔 张奶奶
 *张大叔 张大爷
 *
 *
 *输出:
 *grandchild grandparent
 *张三	张大爷
 *张三	张奶奶
 *张三	王奶奶
 *张三	王大爷
 *张张	张大爷
 *张张	张奶奶
 *张张	王奶奶
 *张张	王大爷
 *
 *
 *reduce端的join:
 *核心思想:在map端对不同来源的数据或者是有不同用处的数据做标记,以便传输到reduce能识别并进行连接找出关系。
 *使用场景:几乎所有业务场景都可以,比较耗时。
 *优点:适用于表全是大表,几乎所有业务场景都可以。
 *缺点:map到reuce的数据传输量大无效数据耗时;在reduce需要对大量无效数据进行连接查找耗时;
 *
 *
 *任务:
 *category
 *cid	parentid	name
 *1		0			家电
 *2		0			服装
 *3		0			食品
 *4		1			洗衣机
 *5		1			冰箱
 *6		2			男装
 *7		2			女装
 *8		3			零食
 *9		3			水果
 *10	4			美的
 *11	5			海尔
 *12	6			衬衫
 *13	7			蓬蓬裙
 *14	8			牛奶
 *
 *
 *输出数据:
 *家电 洗衣机-美的
 *家电 冰箱-海尔
 *服装 男装-衬衫
 *
 *
 *
 */
public class SingleTableDemo  extends ToolRunner implements Tool{

	/**
	 * 自定义的myMapper
	 * @author lyd
	 *
	 */
	static class MyMapper extends Mapper{

		@Override
		protected void map(LongWritable key, Text value,Context context)
				throws IOException, InterruptedException {
			String line = value.toString();
			String lines [] = line.split(" ");
			//定义一个左表 p r-c   父辈 1-孩子   1父关系
			context.write(new Text(lines[1]), new Text("1_"+lines[0]));
			//定义一个右表 c r-p   孩子 2_父母  2 孩子
			context.write(new Text(lines[0]), new Text("2_"+lines[1]));
		}
	}
	
	/**
	 * 自定义MyReducer
	 * @author lyd
	 *
	 */
	static class MyReducer extends Reducer{

		@Override
		protected void reduce(Text key, Iterable value,Context context)
				throws IOException, InterruptedException {
			//定义一个集合存放孙子辈
			List grandChild = new ArrayList();
			//定义一个集合存放祖辈
			List grandParent = new ArrayList();
			
			for (Text s: value) {
				String strs [] = s.toString().split("_");
				//判断r是1还是2 如果是1,则将他的值放孙子辈,如果是2则放到祖辈
				if(strs[0].equals("1")){
					grandChild.add(strs[1]);
				} else if(strs[0].equals("2")){
					grandParent.add(strs[1]);
				}
			}
			
			//嵌套循环
			for (int i = 0; i < grandChild.size(); i++) {
				for (int j = 0; j < grandParent.size(); j++) {
					context.write(new Text(grandChild.get(i)), new Text(grandParent.get(j)));
				}
			}
		}
	}
	
	
	@Override
	public void setConf(Configuration conf) {
		conf.set("fs.defaultFS", "hdfs://hadoop01:9000");
	}

	@Override
	public Configuration getConf() {
		return new Configuration();
	}
	
	/**
	 * 驱动方法
	 */
	@Override
	public int run(String[] args) throws Exception {
		//1、获取conf对象
		Configuration conf = getConf();
		//2、创建job
		Job job = Job.getInstance(conf, "model01");
		//3、设置运行job的class
		job.setJarByClass(SingleTableDemo.class);
		//4、设置map相关属性
		job.setMapperClass(MyMapper.class);
		job.setMapOutputKeyClass(Text.class);
		job.setMapOutputValueClass(Text.class);
		FileInputFormat.addInputPath(job, new Path(args[0]));
		
		//5、设置reduce相关属性
		job.setReducerClass(MyReducer.class);
		job.setOutputKeyClass(Text.class);
		job.setOutputValueClass(Text.class);
		//判断输出目录是否存在,若存在则删除
		FileSystem fs = FileSystem.get(conf);
		if(fs.exists(new Path(args[1]))){
			fs.delete(new Path(args[1]), true);
		}
		FileOutputFormat.setOutputPath(job, new Path(args[1]));
		
		//6、提交运行job
		int isok = job.waitForCompletion(true) ? 0 : 1;
		return isok;
	}
	
	/**
	 * job的主入口
	 * @param args
	 */
	public static void main(String[] args) {
		try {
			//对输入参数作解析
			String [] argss = new GenericOptionsParser(new Configuration(), args).getRemainingArgs();
			System.exit(ToolRunner.run(new SingleTableDemo(), argss));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}

 

你可能感兴趣的:(Java代码,MapReduce,hadoop,MapReduce)