MarReduce小練習 - 多表關聯(使用靜態變數)
阿新 • • 發佈:2018-12-04
題意:
輸入檔案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)));
}
}