我尝试在学生分数示例中使用KeyValueInputFormat
。
这是输入:
s1 10
s2 50
s3 30
s1 100
s1 50
s2 30
s3 70
s3 50
s2 75
我使用KeyValueInputFormat
作为输入格式,因此它将学生姓名(s1,s2 ...)作为键并标记(10,50 ...)作为值。我的目标是找到每个人的总分。所以,我只使用了reducer作为
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:输入map中的值不匹配:expected 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);
}
}
我能够得到正确的输出。有人可以帮帮我吗?
答案 0 :(得分:1)
更改此行:
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)
答案 1 :(得分:1)
问题是您在main方法中声明程序的输出将是Text
类型的键和类型LongWritable
的值。
默认情况下,这也被假定为Mapper的输出类型。
此外,默认映射器(IdentityMapper)还将假设它接收的输入与其输出的类型相同,但在您的情况下,映射器的输入和输出应该是该类型的键值对Text
。
所以,只需在main方法中添加一个命令,指定Mapper的输出应该是Text,Text:
的形式job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(Text.class);
我认为这应该有效。否则,按照Mobin Ranjbar的建议。