版权声明:本文为博主原创文章,未经博主允许不得转载。 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
实现思路
该题重点是两个文件之间存在连接关系,即地址编号,只要输出时按照地址编号寻找其地址即可,主要步骤入下:
- Job驱动类定义静态变量,存储地址编号-地址,这里使用Map集合
- Mapper端按照输入数据的类型分开存储:
- 类型1:格式为地址编号-地址,将该类数据存储到静态变量
- 类型2:格式为公司-地址编号,将该类数据输出到Reducer端
- Reducer端遍历静态变量,按照一定关系输出数据。
重点:
大致步骤如上述1-3点,但其中还有很重要的细节,主要在Mapper端,如:
- 如何判断输入数据的类型,这里采用正则判断。
- maper的格式化是将一行数据读入,在按照空格等分割时,分割如下:
需要做的就是拼接公司名称。
代码
- Job驱动类
public static Map<String, String> numberAddress = new HashMap<>();
- 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));
}
- 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)));
}
}