此map-reduce用于计算“Hadoop:确定指南”中示例的每年和每月的平均温度
输出应该是
年[TAB]月[TAB]平均温度
由于键(年+月)已经合并,是否可以使用substring()和context.write(year [TAB] month [TAB] average_temperature)?或处理此问题的常用方法是什么?像以下(这是不正确的)?
context.write(key.toString()。substring(0,4),key.toString()。substring(4,6),平均值);
protected void reduce(Text key, Iterable<TemperatureAveragingPair> values, Context context) throws IOException, InterruptedException {
int temp = 0;
int count = 0;
for (TemperatureAveragingPair pair : values) {
temp += pair.getTemp().get();
count += pair.getCount().get();
}
average.set(temp / count);
context.write(key, average);
}
完整的代码引用在这里。
https://github.com/bbejeck/hadoop-algorithms/blob/master/src/bbejeck/mapred/aggregation/AverageTemperatureReducer.java
最佳答案
在上课后,有些事情对我来说似乎很奇怪。
首先,您的Mapper输出<Text, IntWritable>
不符合Reducer / Combiner输入<Text, TemperatureAveragingPair>
。这些应该同步,否则作业将失败而在编译中未显示任何问题。
您说“由于键(年+月)已经合并”,我假设NcdcRecordParser
中的以下语句获取年+月(肯定是yyMM格式):
year = record.substring(15, 19);
但上述陈述与之矛盾:
context.write(key.toString().substring(0, 4),key.toString().substring(4, 6), average);
建议使用yyyyMM格式。在前一种情况下,您似乎无处在月份字符串中添加month。
无论如何,让我们说清楚。没错,可以使用
substring
方法将年份和月份分开,如图所示。但是为此,您必须从Mapper
发出相同格式的密钥。接下来,您不需要将TemperatureAveragingPair
用作Reducer
的值,一个简单的IntWritable
就能解决问题并消除异常。现在看起来像:private Text tabKey = new Text();
private StringBuilder builder = new StringBuilder();
public void reduce(Text key, Iterable<IntWritable> values, Context context)
throws IOException, InterruptedException {
int temp = 0;
int count = 0;
for (IntWritable value : values) {
temp += value.get();
count ++;
}
average.set(temp / count);
builder.setLength(0);
builder.append(key.toString());
builder.insert(4, "\t");
tabKey.setText(builder.toString());
context.write(tabKey, average);
}
关于hadoop - 如何在Hadoop的reduce函数中分离键(YearMonth),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/26576850/