我被要求修改 WordCount 示例,以便每个映射器函数在传递之前将其文件中出现的单词相加。例如,而不是:
<help,1>
<you,1>
<help,1>
<me,1>
映射器的输出将是:
<help,2>
<you,1>
<me,1>
那么我会将单词添加到数组中,然后检查出现次数吗?还是有更简单的方法?
String line = value.toString();
StringTokenizer tokenizer = new StringTokenizer(line);
while (tokenizer.hasMoreTokens()) {
word.set(tokenizer.nextToken());
context.write(word, one);
}
您可以定义 Java Map 结构或 Guava Multiset,并计算每个映射器每个单词的出现次数。然后,当映射器结束时,之后运行的清理方法可以将所有部分总和作为映射的输出,如下所示(伪代码):
setup() {
Map<String,Integer> counts = new HashMap<>();
}
map() {
for each word w {
counts.put(w, counts.get(w)+1); //or 1, if counts.get(w) returns null
}
}
cleanup() {
for each key w of counts.keySet {
context.write(w, counts.get(w));
}
}
引用映射器的文档(版本 2.6.2):
Hadoop Map-Reduce框架为作业的InputFormat生成的每个InputSplit生成一个映射任务。映射器实现可以通过 JobContext.getConfiguration() 访问作业的配置。
该框架首先调用setup(org.apache.hadoop.mapreduce.Mapper.Context),然后为InputSplit中的每个键/值对调用map(Object,Object,Context)。最后调用清理(上下文)。
除此之外,您还可以考虑使用组合器作为替代方案。