MarReduce小练习 - 多表关联(使用静态变量)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_38038143/article/details/84665522

题意:

输入文件1:地址编号-地址
输入文件2:公司-地址编号
根据两个输入文件,输出公司所在的地址。
格式如下:

1.输入文件1:
address.txt:
1  Beijing
2  Guangzhou
3  Shenzhen
4  Xian


2.输入文件2:
factory.txt:
Beijing Red Star         1
Shenzhen Thunder     3
Guangzhou Honda     2
Beijing Rising          1
Guangzhou Development Bank    2
Tencent    3
Back of Beijing   1


3.输出结果:

        factory                    city
Beijing Red Star                  Beijing
 Shenzhen Thunder                 Shenzhen
 Guangzhou Honda                  Guangzhou
 Beijing Rising                   Beijing
 Guangzhou DevelopmentBank        Guangzhou
 Tencent                          Shenzhen
 Back of Beijing                   Beijing

实现思路

该题重点是两个文件之间存在连接关系,即地址编号,只要输出时按照地址编号寻找其地址即可,主要步骤入下:

  1. Job驱动类定义静态变量,存储地址编号-地址,这里使用Map集合
  2. Mapper端按照输入数据的类型分开存储:
  • 类型1:格式为地址编号-地址,将该类数据存储到静态变量
  • 类型2:格式为公司-地址编号,将该类数据输出到Reducer端
  1. Reducer端遍历静态变量,按照一定关系输出数据。
重点:

大致步骤如上述1-3点,但其中还有很重要的细节,主要在Mapper端,如:

  1. 如何判断输入数据的类型,这里采用正则判断。
  2. maper的格式化是将一行数据读入,在按照空格等分割时,分割如下:
    在这里插入图片描述
    需要做的就是拼接公司名称。

代码

  1. Job驱动类
public static Map<String, String> numberAddress = new HashMap<>();
  1. Mapper
		StringTokenizer stringTokenizer = new StringTokenizer(value.toString()); // 好像用String.split(" ")分割更简单点
		String column1 = stringTokenizer.nextToken();
		/*
		 *  读取文件内容可分为两种:编号-地址、公司-地址编号, 处理方法如下:
		 *  使用正则表达式判断数据的类型
		 *  将属于编号-地址类数据存入静态便利
		 *  将属于公司-地址编号类输出到reducer端
		 */
		// 正则
		Matcher matcher = Pattern.compile("^[0-9]*$").matcher(column1);
		if (matcher.find()) { // 匹配到地址编号,属于编号-地址类型数据
			MTLinkJob.numberAddress.put(column1, stringTokenizer.nextToken());
		} else { // 属于公司-地址编号类型
			// 由于公司名称会被分割,所以先存储分割的片段,最后一个片段则为地址编号
			String companyName = "" + column1; // 公司名称
			String numberOfaddress = null;
			while (stringTokenizer.hasMoreTokens()) {
				if (stringTokenizer.countTokens() > 1) { // countTokens=剩余数量。不是最后一个片段则拼接为公司名称
					companyName = companyName + " " + stringTokenizer.nextToken().toString();
				} else { // 最后一个片段为地址编号
					numberOfaddress = stringTokenizer.nextToken().toString();
				}
			}
			context.write(new Text(companyName), new Text(numberOfaddress));
		}
  1. Reducer
	private int tol = 0; // 写入行首提示
	@Override
	protected void reduce(Text key, Iterable<Text> values, Reducer<Text, Text, Text, Text>.Context context)
			throws IOException, InterruptedException {
		if (tol++ == 0) {
			context.write(new Text("\tfactory"), new Text("\t\t\t\t\tcity"));
		}
		// 根据key,查找静态变量来确定地址
		String numberOfaddress = values.iterator().next().toString();
		if (MTLinkJob.numberAddress.containsKey(numberOfaddress)) {
			// 控制输出对其
			String spaceCounts = "";
			for (int i=0; i<30-key.toString().length(); i++) {
				spaceCounts = spaceCounts + " ";
			}
			context.write(new Text(key), new Text(spaceCounts + MTLinkJob.numberAddress.get(numberOfaddress)));
		}
	}

完整项目代码见GitHub:https://github.com/GYT0313/MapReducePractice

猜你喜欢

转载自blog.csdn.net/qq_38038143/article/details/84665522