這裏你不需要兩個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")
我不想讓我的例子更加複雜且不易讀,因爲它包含了這一點,但它應該很簡單,並且應該可以節省很多性能。
感謝您的答案,但對於我的問題,我必須計算每個不同情節彙總的單詞出現次數。例如:如果我有一個情節摘要「489373跳過牛的快速棕色」和「838399緩慢的棕色海龜咬一頭牛」,則輸出的示例將是「牛\ t 489373 1,838399 1」,「 – grizzle
」那麼你在描述中一點都不清楚,這是令人沮喪的,因爲我在我的答案中付出了很多努力。我爲所問的問題寫了正確的答案。對我的例子來說,它只是一個小小的變化,它仍然不需要多個MR作業或自定義的Writable。這只是對Reducer邏輯的一個小改動。 –
對此感到抱歉。因此,要修改它,當reducer將所有movieID添加到moviesList時,將會有重複,這意味着該字在劇情彙總中多次出現。所以我只需要通過並簡化moviesList。 – grizzle