MarReduce小練習 - 單表關聯(使用靜態變數)
阿新 • • 發佈:2018-12-04
題意:
根據兒子、父母關係,輸出孫子、爺奶關係:
輸入: 輸出:
程式的執行瀏覽如同 wordcount 一樣,輸入輸出幾乎沒有什麼改動,該程式的輸入輸出結果流程如下圖(主要是在第二個箭頭中如何按照爺孫關係輸出):
重點是如何在reducer端輸出時按照爺孫關係輸出,這裡在job驅動類中定義一個靜態變數relationship(相當於全域性變數),其定義如下:
public static Map<String, ArrayList<String>> relationship = new HashMap<>();
relationship是一個Map集合,實現key、value的儲存:
- 字串型別的Key儲存輸入資料的“子”
- 列表型別的Value儲存輸入資料的“父”
當map端執行結束,將得到兩個結果:
- mapper輸出到reducer的結果:
<Jack <Jesse, Alice>>
<Jone <Lucy, Jack>>
<Lucy <Mary, Ben>>
<Mark <Alma, Terry>>
<Philip <Terry, Alma>>
<Terry <Alice, Jesse>>
<Tom <Jack, Lucy>>
- 最終relationship儲存的資料如下:
key , value Jone Lucy, Jack] Jack [Alice, Jesse] Philip [Terry, Alma] Lucy [Mary, Ben] Terry [Alice, Jesse] Mark [Terry, Alma] Tom [Lucy, Jack]
因此,在reducer端只需要根據上面1、2點的結果進行遍歷,按照關係輸出,即可得到最終的結果。
程式碼:
1. 其中STLinkJob為主函式(驅動類),包含配置資訊及靜態變數:
public static Map<String, ArrayList<String>> relationship = new HashMap<>();
2. Mapper端程式碼:
StringTokenizer stringTokenizer = new StringTokenizer(value.toString());
String sun = stringTokenizer.nextToken();
String par = stringTokenizer.nextToken();
// 利用集合將父子關係儲存記錄
ArrayList<String> arrayList = new ArrayList<>();
if (!STLinkJob.relationship.containsKey(sun)) { // 第一次記錄
arrayList.add(par);
STLinkJob.relationship.put(sun, arrayList);
} else { // 第二次記錄
arrayList = STLinkJob.relationship.get(sun);
arrayList.add(par);
STLinkJob.relationship.put(sun, arrayList);
}
context.write(new Text(sun), new Text(par));
3. Reducer端程式碼:
ArrayList<String> grands = new ArrayList<>();
// 通過遍歷父母,查詢map關係來確定爺奶
for (Text parent : values) { // 父母
String par = parent.toString();
if (STLinkJob.relationship.containsKey(par)) {
grands = STLinkJob.relationship.get(par);
for (String grand : grands) { // 爺奶
context.write(key, new Text(grand));
}
}
}