Mapreduce之InnerJoin

內連接
兩個文件 顯示兩個文件的數據
根據兩個文件的數據進行判斷
讀取每一行數據
數據長度==2 那麼就是第一個文件
長度==3那麼就是第二個文件
第一個文件使用a#開頭
第二個文件使用b#開頭
兩個文件使用相同的key value進行合併
獲取以爲開頭a 並進行切分
獲取以b開頭 並進行切分
把切的數據封裝 根據key相同聚合value

 

package com.hnxy.mr.join;

import java.io.IOException;
import java.util.LinkedList;
import java.util.List;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.conf.Configured;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.NullWritable;
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.Tool;
import org.apache.hadoop.util.ToolRunner;

import com.hnxy.mr.entity.AreaInfoWritable;
import com.hnxy.mr.entity.WordWritable;
import com.hnxy.mr.max.MaxMinWord;
import com.hnxy.mr.max.MaxMinWord.MWReducer;

public class InnerJoin extends Configured implements Tool {
	// 1 北京
	// 1 2010 1962
	// 合併查詢
	public static class InnerJoinMapper extends Mapper<LongWritable, Text, Text, Text> {
		// 定義變量
		private String str = "";
		private String[] strs = null;
		// 定義輸出值
		private Text outkey = new Text();
		private Text outval = new Text();

		@Override
		protected void map(LongWritable key, Text value, Mapper<LongWritable, Text, Text, Text>.Context context)
				throws IOException, InterruptedException {
			// 有兩個文件 一個是兩個字段一個是三個字段
			// 首先獲得每一行數據
			strs = value.toString().split("\t");
			if (strs.length == 2 && null != strs) {
				// id
				outkey.set(strs[0]);
				// 省份信息
				outval.set("a#" + strs[1]);
				// 寫入這一行數據
				context.write(outkey, outval);
			} else if (strs.length == 3 && null != strs) {
				// id
				outkey.set(strs[0]);
				outval.set("b#" + strs[1] + "\t" + strs[2]);
				// 寫入一個數據
				context.write(outkey, outval);
			} else {
				context.getCounter("erro_line", "count").increment(1);
			}

		}
	}

	public static class InnerJoinReducer extends Reducer<Text, Text, AreaInfoWritable, NullWritable> {
		// 定義返回值對象
		private AreaInfoWritable outkey = new AreaInfoWritable();
		private String aname = null;
		private List<String> year = new LinkedList<String>();
		private List<String> count = new LinkedList<String>();
		private String tmpSplit = null;

		@Override
		protected void reduce(Text key, Iterable<Text> values,
				Reducer<Text, Text, AreaInfoWritable, NullWritable>.Context context)
				throws IOException, InterruptedException {
			// 先按照a b切 在根據b的 按照\t切分
			year.clear();
			count.clear();
			aname = null;
			for (Text t : values) {
				if (t.toString().startsWith("a")) {
					// 省份信息
					aname = t.toString().split("#")[1];
				} else if (t.toString().startsWith("b")) {
					tmpSplit = t.toString().split("#")[1];
					year.add(tmpSplit.split("\t")[0]); // 年
					count.add(tmpSplit.split("\t")[1]); // 人
				}
			}

			// 判斷是否失效
			if (year.size() > 0 && count.size() > 0 && null != aname && !aname.trim().equals("")) {
				for (int i = 0; i < year.size(); i++) {
					outkey.setAid(Long.parseLong(key.toString()));
					outkey.setAreaName(aname);
					outkey.setCount(Long.parseLong(count.get(i)));
					outkey.setYear(year.get(i));
					// 寫入數據
					context.write(outkey, NullWritable.get());
				}
			}
		}
	}

	@Override
	public int run(String[] args) throws Exception {
		// 創建方法的返回值
		int count = 0;
		// 創建核心配置對象
		Configuration conf = this.getConf();
		// 創建一個任務
		Job job = Job.getInstance(conf, "maxword");
		// 配置任務打包類
		job.setJarByClass(InnerJoin.class);
		// 設置MapReduce類
		job.setMapperClass(InnerJoinMapper.class);
		job.setReducerClass(InnerJoinReducer.class);
		// 設置 map 階段 和 reduce 節點的 輸出數據類型
		job.setMapOutputKeyClass(Text.class);
		job.setMapOutputValueClass(Text.class);
		job.setOutputKeyClass(AreaInfoWritable.class);
		job.setOutputValueClass(NullWritable.class);
		// 設置文件路徑
		Path in = new Path(args[0]);
		Path out = new Path(args[1]);
		// 設置hdfs操作對象
		FileSystem fs = FileSystem.get(conf);
		// 綁定文件輸出輸入目錄
		FileInputFormat.addInputPath(job, in);
		FileOutputFormat.setOutputPath(job, out);
		// 自動刪除
		if (fs.exists(out)) {
			fs.delete(out, true);
			// 提示
			System.out.println(job.getJobName() + "'s Path Output is deleted");
		}
		// 執行
		boolean con = job.waitForCompletion(true);
		// 返回
		if (con) {
			System.out.println("成功");
		} else {
			System.out.println("失敗");
		}
		return 0;
	}

	public static void main(String[] args) throws Exception {
		System.exit(ToolRunner.run(new InnerJoin(), args));
	}

}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章