私は自分のニーズに合うように既存の問題を微調整しようとしています。
基本的に入力は単純なテキストです。処理してキーと値のペアをレデューサーに渡します。jsonを作成します。キーはありますが値はありません。マッパー:
入力:テキスト/テキスト
出力:テキスト/テキスト
レデューサー:テキスト/テキスト
出力:テキスト/なし
私の署名は次のとおりです。
public class AdvanceCounter {
/**
* The map class of WordCount.
*/
public static class TokenCounterMapper
extends Mapper<Object, Text, Text, Text> { // <--- See this signature
public void map(Object key, Text value, Context context) // <--- See this signature
throws IOException, InterruptedException {
context.write(key,value); //both are of type text OUTPUT TO REDUCER
}
}
public static class TokenCounterReducer
extends Reducer<Text, Text, Text, **NullWritable**> { // <--- See this signature Nullwritable here
public void reduce(Text key, Iterable<Text> values, Context context) // <--- See this signature
throws IOException, InterruptedException {
for (Text value : values) {
JSONObject jsn = new JSONObject();
//String output = "";
String[] vals = value.toString().split("\t");
String[] targetNodes = vals[0].toString().split(",",-1);
try {
jsn.put("source",vals[1]);
jsn.put("targets",targetNodes);
context.write(new Text(jsn.toString()),null); // no value
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public static void main(String[] args) throws Exception {
Configuration conf = new Configuration();
String[] otherArgs = new GenericOptionsParser(conf, args).getRemainingArgs();
Job job = new Job(conf, "Example Hadoop 0.20.1 WordCount");
// ...
//
job.setOutputValueClass(NullWritable.class);
FileInputFormat.addInputPath(job, new Path(otherArgs[0]));
FileOutputFormat.setOutputPath(job, new Path(otherArgs[1]));
System.exit(job.waitForCompletion(true) ? 0 : 1);
}
}
しかし、実行時にこのエラーが発生します:
13/06/04 13:08:26 INFO mapred.JobClient: Task Id : attempt_201305241622_0053_m_000008_0, Status : FAILED
Java.io.IOException: Type mismatch in value from map: expected org.Apache.hadoop.io.NullWritable, recieved org.Apache.hadoop.io.Text
at org.Apache.hadoop.mapred.MapTask$MapOutputBuffer.collect(MapTask.Java:1019)
at org.Apache.hadoop.mapred.MapTask$NewOutputCollector.write(MapTask.Java:691)
at org.Apache.hadoop.mapreduce.TaskInputOutputContext.write(TaskInputOutputContext.Java:80)
at org.sogou.Stinger$TokenCounterMapper.map(Stinger.Java:72)
at org.sogou.Stinger$TokenCounterMapper.map(Stinger.Java:1)
at org.Apache.hadoop.mapreduce.Mapper.run(Mapper.Java:144)
at org.Apache.hadoop.mapred.MapTask.runNewMapper(MapTask.Java:764)
at org.Apache.hadoop.mapred.MapTask.run(MapTask.Java:370)
at org.Apache.hadoop.mapred.Child$4.run(Child.Java:255)
at Java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.Subject.doAs(Subject.Java:396)
at org.Apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.Java:1093)
at org.Apache.hadoop.mapred.Child.main(Child.Java:249)
マップ出力タイプを指定していないため、レデューサーに設定したものと同じようになります。これは、マッパーには正しくないText
とNullWritable
です。混乱を避けるために、次のことを行う必要があります。マッパーとレデューサーの両方にすべてのタイプを指定することをお勧めします。
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(Text.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(NullWritable.class);