2015-11-13 100 views
2

我正在處理一組MapReduce作業,這些作業將劇情摘要列表轉換爲映射到movieID的每個單詞的索引以及它被使用了多少次。我有一個工作需要輸入,並創建一個包含單詞,來自電影的節點的鏈接列表以及次數。我的第二份工作是使用這個LinkedList,並使用單詞作爲關鍵字,將影片ID和出現次數作爲值,並將映射到每個映射到每個電影的每個單詞的索引以及出現次數都吐出。使用某些數據類型作爲MapReduce作業的輸入。

當調用FileInputFormat.addInputPath()時,我可以使用Path()或每個元素用逗號分隔的字符串。用LinkedList保存所有的數據並不難,但只要讓Mapper使用LinkedList作爲輸入就會更好。

我已閱讀關於鏈接MapReduce工作,所以請不要給我一個鏈接到雅虎開發者頁面。

回答

1

這裏你不需要兩個MapReduce作業(或者一個LinkedList)。我們可以將其視爲字數統計的一種變體,但可以在輸出中添加一個電影ID列表。

地圖輸入:

354757\tToys come alive 
432984\tMore toys 

地圖代碼:

String[] idAndWords = input.split("\\t"); 

for(String word : idAndWords[1].split(" ")) { 
    //Do whatever cleansing you want here - remove punctuation, lowercase etc. 
    output.write(word,idAndWords[0]); 
} 

地圖輸出:

("toys","354757") 
("come","354757") 
("alive","354757") 
("more","432984") 
("toys","432984") 

減速代碼:

//Maps movie IDs to occurrences 
Map<String,Int> movieMap = new HashMap<>(); 
//In here is the list of movie IDs for each word 
for(String val : values) { 
    if(!movieMap.contains(val)) { 
     movieMap.put(val,1); 
    } else { 
     movieMap.put(val,movieMap.get(val)+1); 
    } 
} 
output.write(NullWritable.get(),key+"\t"+movieMap); 

減速機的輸出:

toys\t[(3547571),(432984,1)] 
come\t[(354757,1)] 
alive\t[(354757,1)] 
more\t[(432984,1)] 

現在你已經不再需要自定義Writable,而且它比邏輯的十幾行,而不是我所想的少會是一個非常複雜的兩個鏈式MR作業集。

效率擴展:

你可以使它更有效率加入了計數到映射器輸出 - 與當前執行,則情節主線「狗吃狗」會導致地圖輸出:

("dog","354757") 
("eat","354757") 
("dog","354757") 

,而你可以將它通過添加計數器和掃描整個行輸出之前減少到兩個記錄:

("dog","354757\t2") 
("eat","354757\t1") 

我不想讓我的例子更加複雜且不易讀,因爲它包含了這一點,但它應該很簡單,並且應該可以節省很多性能。

+0

感謝您的答案,但對於我的問題,我必須計算每個不同情節彙總的單詞出現次數。例如:如果我有一個情節摘要「489373跳過牛的快速棕色」和「838399緩慢的棕色海龜咬一頭牛」,則輸出的示例將是「牛\ t 489373 1,838399 1」,「 – grizzle

+0

」那麼你在描述中一點都不清楚,這是令人沮喪的,因爲我在我的答案中付出了很多努力。我爲所問的問題寫了正確的答案。對我的例子來說,它只是一個小小的變化,它仍然不需要多個MR作業或自定義的Writable。這只是對Reducer邏輯的一個小改動。 –

+0

對此感到抱歉。因此,要修改它,當reducer將所有movieID添加到moviesList時,將會有重複,這意味着該字在劇情彙總中多次出現。所以我只需要通過並簡化moviesList。 – grizzle