此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/

10-16 01:55