如何为这种情况编写MapReduce代码?

时间:2015-08-25 13:18:27

标签: java hadoop mapreduce hive

说我有一个输入文件,如下所示

dept_id emp_id  salary
1       13611   1234
2       13609   3245
3       13612   3251
2       13623   1232
1       13619   6574
3       13421   234

现在我想找到每个部门的平均工资。像下面的Hive查询一样:

SELECT dept_id, avg(salary) FROM dept GROUP BY dept_id

这将返回输出:

dept_id avg_sal
----------------
  1     3904.0
  2     2238.5
  3     1742.5

现在,我想要做的是生成相同的输出,但使用mapreduce框架。那怎么写呢?提前谢谢!

3 个答案:

答案 0 :(得分:2)

  

重要:   在尝试实现之前,首先尝试MapReduce中的一些基本示例,如实现字数统计程序,理解逻辑,甚至在此之前,阅读有关MapReduce如何工作的书籍或教程。

聚合内容(如查找平均值)的想法是,您在映射阶段按键(部门ID)进行分组,然后在减少阶段减少特定部门的所有工资。

以更正式的方式:

<强> MAP:

输入:表示工资记录的行(即dep_id,emp_id,salary)
输出(键,值):( dep_id,salary)

<强> REDUCE:

输入(键,值):( dep_id,工资:具有此dep_id的工资值列表)
输出(键,值):( dep_id,avg(工资))

这样,属于同一部门的所有工资都将由同一个减速机处理。你需要在reducer中做的就是找到输入值的平均值。

答案 1 :(得分:2)

代码----

import java.io.IOException;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.FloatWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

public class AverageSalary {
  public static class AvgMapper
       extends Mapper<Object, Text, Text, FloatWritable>{
    private Text dept_id = new Text();
    private FloatWritable salary = new FloatWritable(); 
    public void map(Object key, Text value, Context context
                    ) throws IOException, InterruptedException {
        String values[] = value.toString().split("\t");
        dept_id.set(values[0]);
        salary.set(Float.parseFloat(values[2]));
        context.write(dept_id, salary);
    }
  }

  public static class AvgReducer
       extends Reducer<Text,FloatWritable,Text,FloatWritable> {
    private FloatWritable result = new FloatWritable();

    public void reduce(Text key, Iterable<FloatWritable> values,
                       Context context
                       ) throws IOException, InterruptedException {
      float sum = 0;
      float count = 0;
      for (FloatWritable val : values) {
        sum += val.get();
        count++;
      }
      result.set(sum/count);
      context.write(key, result);
    }
  }

  public static void main(String[] args) throws Exception {
    Configuration conf = new Configuration();
    Job job = Job.getInstance(conf, "average salary");
    job.setJarByClass(AverageSalary.class);
    job.setMapperClass(AvgMapper.class);
    job.setCombinerClass(AvgReducer.class);
    job.setReducerClass(AvgReducer.class);
    job.setOutputKeyClass(Text.class);
    job.setOutputValueClass(FloatWritable.class);
    FileInputFormat.addInputPath(job, new Path("/home/kishore/Data/mapreduce.txt"));  // input path
    FileOutputFormat.setOutputPath(job, new Path("/home/kishore/Data/map3")); // output path
    System.exit(job.waitForCompletion(true) ? 0 : 1);
  }
}

output 
1   3904.0
2   2238.5
3   1742.5

答案 2 :(得分:0)

如果您尚未完成任何培训计划,请访问edureka上的免费视频,以便更好地理解概念:Map Reduce

映射

映射器将输入键/值对映射到一组中间键/值对。

地图是将输入记录转换为中间记录的各个任务。转换后的中间记录不需要与输入记录的类型相同。给定的输入对可以映射到零个或多个输出对。

减速

Reducer将一组中间值减少到一个较小的值集合。

作业的减少次数由用户通过Job.setNumReduceTasks(int)设置。

Apache Hadoop网站上的工作示例:Word Count example

对于您的用例,简单使用单词计数示例是不够的。 您必须在Mapper上使用Combiner和分区器,因为您使用的是Group by。访问此视频:Advanced Map reduce