我尝试在学生成绩示例中使用KeyValueInputFormat
。这是输入:
S1 10
S2 50
S3 30
S1 100
S1 50
S2 30
S3 70
S3 50
S2 75
我使用 KeyValueInputFormat
作为输入格式,因此它带来了学生姓名 (s1,s2...) 作为键和标记 (10,50...) 作为值。我的目标是找到每个人的总分。所以,我只使用减速器作为
public class MarkReducer extends Reducer<Text,Text,Text,LongWritable>{
public void reduce(Text key, Iterable<Text> values,Context ctx) throws IOException, InterruptedException{
long sum = 0;
for(Text value:values){
sum+= Long.parseLong(value.toString());
}
ctx.write(key, new LongWritable(sum));
}
}
我既没有在作业中创建也没有提及映射器。我收到错误
错误:java.io.IOException:映射中的值类型不匹配:预期的org.apache.hadoop.io.LongWritable,收到org.apache.hadoop.io.Text
但是如果我使用虚拟映射器,例如,
public class MarkMapper extends Mapper<Text,Text,Text,Text> {
public void map(Text key, Text value, Context ctx) throws IOException, InterruptedException{
ctx.write(key, value);
}
}
我能够获得正确的输出。有人可以帮我吗?
问题是您在 main 方法中声明程序的输出将是 Text
类型的键和 LongWritable
类型的值。默认情况下,这也假定为映射器的输出类型。
此外,默认映射器(IdentityMapper)还将假定它收到的输入也与其输出属于同一类型,但在您的情况下,映射器的输入和输出应该是类型为 Text
的键值对。
因此,只需在main方法中添加一个命令,以指定映射器的输出应为Text,Text的形式:
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(Text.class);
我认为这应该有效。否则,请按照Mobin Ranjbar的建议进行操作。
更改此行:
ctx.write(key, new LongWritable(sum));
自
ctx.write(key, new Text(sum));
在您的减速器中。或者将reduce(Text key, Iterable<Text> values,Context ctx)
更改为reduce(Text key, Iterable<LongWritable> values,Context ctx)