我有以下格式的特定班级学生的数据
StudentId@CourseId@Marks1@Marks2@Marks3@Marks4@Marks5
01001@104@13@18@25@86@23
01001@106@58@30@10@12@59
01001@108@60@81@97@83@26
01001@110@68@95@11@73@63
01001@112@55@22@74@71@22
01002@104@20@72@76@28@99
01002@106@52@17@20@67@91
01002@108@18@46@61@73@14
01002@110@86@59@50@35@65
01002@112@45@76@97@37@17
.......
我想计算5个不同考试中5个不同课程(由5个不同课程ID给出)的学生得分的平均值。
以上的我的Map和Reduce Classes如下:
public static class Map extends MapReduceBase implements Mapper<LongWritable,Text,Text,DoubleWritable>{
private Text SID=new Text();
public void map(LongWritable key, Text value, OutputCollector<Text,DoubleWritable> output,Reporter reporter)throws IOException{
String data=value.toString();
String arr[]=data.split("@");
int i=2;
double score=0;
while(i<arr.length){
score+=Integer.parseInt(arr[i]);
i++;
}
//Dividing The Score to give the average score in a particular course
score=score/5;
SID.set(arr[0]);
output.collect(SID,new DoubleWritable(score));
}
}
和
public static class Reduce extends MapReduceBase implements Reducer<Text,DoubleWritable,Text,DoubleWritable>{
public void reduce(Text key,Iterator<DoubleWritable> values,OutputCollector<Text,DoubleWritable> output,Reporter reporter)throws IOException{
double Total=0.0;
while(values.hasNext()){
Total+=values.next().get();
}
//Dividing By 5 to obtain the average score for a particular student
output.collect(key,new DoubleWritable((Total/5)));
}
}
此外,在主类中,除了定义其他配置外,我还将上述Reduce
类设置为Reducer
类和Combiner
类。
然而,我获得的输出如下
01001 9.879999999999999
01002 10.568
01003 8.712
01004 10.68
01005 9.335999999999999
....
这表明学生的总分除以125而不是25。
但是,从score=score/5
类中删除语句Map
时,
我得到了正确的结果。现在从我能理解的(并且不太确定),这是因为在这种情况下Reducer
和Combiner
类是相同的。是这样吗?
在这种情况下,Combiner
类如何工作?
答案 0 :(得分:3)
执行映射后,在每个节点上执行组合器。
然而,只需要在总和的最后除以5(不同课程的数量)。因此,您只能在减速器的末端划分,而不能在合并器的末尾划分。
基本上你可以: