如何在Hadoop中的reduce函数中分离键(YearMonth)

时间:2014-10-26 19:14:08

标签: hadoop mapreduce

此map-reduce用于计算" Hadoop:定义指南"

中的示例的每年和每月的平均温度

输出应为

年[TAB]月[TAB] average_temperature

由于密钥(年份+月份)已经合并,是否可以使用substring()和context.write(年[TAB]月[TAB] average_temperature)?或者处理这个问题的常用方法是什么?如下(不正确)?

context.write(key.toString()。substring(0,4),key.toString()。substring(4,6),average);

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

1 个答案:

答案 0 :(得分:0)

经过课程,有些事情对我来说很奇怪。

首先,您的Mapper输出<Text, IntWritable>不符合Reducer / Combiner输入<Text, TemperatureAveragingPair>。这些应该是同步的,否则作业将失败而不会在编译中出现任何问题。

你说&#39;由于密钥(年+月)已合并&#39; ,我假设NcdcRecordParser中的以下陈述取得年份+月份(肯定在yyMM格式):

 year = record.substring(15, 19);

但上述陈述与之相矛盾:

context.write(key.toString().substring(0, 4),key.toString().substring(4, 6), average);

表示yyyyMM格式。在上一种情况下,您似乎无法将月份添加到年份字符串中。

无论如何,让我们明白这一点。您是对的,您可以使用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);
}