1. 程式人生 > >MarReduce小練習 - 單表關聯(使用靜態變數)

MarReduce小練習 - 單表關聯(使用靜態變數)

題意:

根據兒子、父母關係,輸出孫子、爺奶關係:

輸入:                                      輸出:
在這裡插入圖片描述

程式的執行瀏覽如同 wordcount 一樣,輸入輸出幾乎沒有什麼改動,該程式的輸入輸出結果流程如下圖(主要是在第二個箭頭中如何按照爺孫關係輸出):


在這裡插入圖片描述

重點是如何在reducer端輸出時按照爺孫關係輸出,這裡在job驅動類中定義一個靜態變數relationship(相當於全域性變數),其定義如下:

public static Map<String, ArrayList<String>> relationship = new HashMap<>();

relationship是一個Map集合,實現key、value的儲存:

  • 字串型別的Key儲存輸入資料的“子”
  • 列表型別的Value儲存輸入資料的“父”

當map端執行結束,將得到兩個結果:

  1. mapper輸出到reducer的結果:
<Jack  <Jesse, Alice>> 
<Jone  <Lucy, Jack>> 
<Lucy  <Mary, Ben>>
<Mark  <Alma, Terry>>
<Philip  <Terry, Alma>>
<Terry   <Alice, Jesse>>
<Tom  <Jack, Lucy>>
  1. 最終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));
        }
    }
}
完整程式碼,GitHub:
https://github.com/GYT0313/MapReducePractice

完!