编辑两个文本文档score1.txt(存放了两门课的成绩)和score2.txt(存放了一门课的成绩)。 两个文本的格式相同,包含两列:学号,成绩;两列之间使用英文逗号分隔。编写MapReduce程序用来求每个学生的平均分。
时间: 2024-11-29 17:32:38 浏览: 19
编辑`score1.txt`和`score2.txt`文件的内容时,假设它们的结构都是类似这样的:
```txt
1001,85
1002,90
1003,78
...
```
其中第一列是学生学号,第二列是该学生的成绩。
为了使用MapReduce计算每个学生的平均分数,首先需要定义Mapper和Reducer步骤。在这个例子中,我们可以使用Hadoop MapReduce框架来实现。
**Mapper阶段**:
- 输入键值对会被解析成 `(null, scoreLine)` 形式的键值对,其中 `scoreLine` 是字符串形式的学生记录。
- Mapper函数会对每一行数据进行处理,将学号(可以是分割后的第一个字段,例如通过 `split(",")`)作为键(key),原始分数作为值(value)。
- 输出将是 `(studentID, (1, score))` 的键值对,表示每个学生对应的计数和分数。
**Combiner阶段**:
- 如果没有配置Combiner,那么在Reducer之前,所有Mapper的任务会先在网络中汇聚,然后由Reducer处理。这个阶段是可选的,如果网络带宽允许,可以在这里减少数据传输量。
- Combiner会对Mapper阶段的结果进行局部聚合,即累加每个学生的分数计数,并保持总和。
**Reducer阶段**:
- Reducer收到的是 `(studentID, (count, sumScore))` 的键值对集合,它会计算每个学生的平均分:`average = sumScore / count`。
- 输出将是 `(studentID, average)` 的键值对。
以下是伪代码示例:
```java
// Mapper.java
import java.io.IOException;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;
public class ScoreMapper extends Mapper<LongWritable, Text, Text, IntWritable> {
private final static IntWritable one = new IntWritable(1);
private Text studentID = new Text();
public void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
String[] fields = value.toString().split(",");
studentID.set(fields[0]); // 学号
context.write(studentID, one); // 输出 (studentID, 1)
}
}
// Reducer.java
import java.io.IOException;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;
public class AverageReducer extends Reducer<Text, IntWritable, Text, FloatWritable> {
private IntWritable totalCount = new IntWritable();
private FloatWritable avgScore = new FloatWritable();
public void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {
for (IntWritable count : values) {
totalCount.add(count.get());
}
avgScore.set(totalCount.get() == 0 ? 0 : totalCount.get() / totalCount.get()); // 计算平均分
context.write(key, avgScore); // 输出 (studentID, average)
}
}
```
**Driver code** (主脚本):
- 设置Mapper和Reducer类,并在Job中指定输入、输出路径以及分片的数量。
阅读全文