2011-12-16 20 views
6

Esto puede parecer una pregunta estúpida, pero no veo el problema en mis tipos en mi código mapreduce para hadoopclase de clave incorrecto: El texto no es IntWritable

Como se indica en la pregunta el problema es que es esperando IntWritable pero le estoy pasando un objeto de texto en collector.collect del reductor.

Mi configuración del trabajo tiene las siguientes clases de salida asignador:

conf.setMapOutputKeyClass(IntWritable.class); 
conf.setMapOutputValueClass(IntWritable.class); 

Y las siguientes clases de salida del reductor:

conf.setOutputKeyClass(Text.class); 
conf.setOutputValueClass(IntWritable.class); 

Mi clase de mapeo tiene la siguiente definición:

public static class Reduce extends MapReduceBase implements Reducer<IntWritable, IntWritable, Text, IntWritable> 

con la función requerida:

public void reduce(IntWritable key, Iterator<IntWritable> values, OutputCollector<Text,IntWritable> output, Reporter reporter) 

Y entonces se produce un error cuando llamo:

output.collect(new Text(),new IntWritable()); 

Soy bastante nuevo para mapear reducir, pero todos los tipos parecen coincidir, compila pero luego falla en esa línea diciendo que su esperando una IntWritable como la clave para la clase de reducción. Si importa que estoy usando la versión 0.21 de Hadoop

Aquí está mi clase de mapa:

public static class Map extends MapReduceBase implements Mapper<LongWritable, Text, IntWritable, IntWritable> { 
    private IntWritable node = new IntWritable(); 
    private IntWritable edge = new IntWritable(); 

    public void map(LongWritable key, Text value, OutputCollector<IntWritable, IntWritable> output, Reporter reporter) throws IOException { 
     String line = value.toString(); 
     StringTokenizer tokenizer = new StringTokenizer(line); 

     while (tokenizer.hasMoreTokens()) { 
      node.set(Integer.parseInt(tokenizer.nextToken())); 
      edge.set(Integer.parseInt(tokenizer.nextToken())); 
      if(node.get() < edge.get()) 
       output.collect(node, edge); 
     } 
    } 
} 

y mi clase de reducir:

public static class Reduce extends MapReduceBase implements Reducer<IntWritable, IntWritable, Text, IntWritable> { 

    IntWritable $ = new IntWritable(Integer.MAX_VALUE); 
    Text keyText = new Text(); 

    public void reduce(IntWritable key, Iterator<IntWritable> values, OutputCollector<Text, IntWritable> output, Reporter reporter) throws IOException { 
     ArrayList<IntWritable> valueList = new ArrayList<IntWritable>(); 

     //outputs original edge pair as key and $ for value 
     while (values.hasNext()) { 
      IntWritable value = values.next(); 
      valueList.add(value); 
      keyText.set(key.get() + ", " + value.get()); 
      output.collect(keyText, $); 
     } 

     //outputs all the 2 length pairs 
     for(int i = 0; i < valueList.size(); i++) 
      for(int j = i+1; i < valueList.size(); j++) 
       output.collect(new Text(valueList.get(i).get() + ", " + valueList.get(j).get()), key); 
    } 
} 

y la configuración de mi trabajo:

JobConf conf = new JobConf(Triangles.class); 
conf.setJobName("mapred1"); 

conf.setMapOutputKeyClass(IntWritable.class); 
conf.setMapOutputValueClass(IntWritable.class); 

conf.setOutputKeyClass(Text.class); 
conf.setOutputValueClass(IntWritable.class); 

conf.setMapperClass(Map.class); 
conf.setCombinerClass(Reduce.class); 
conf.setReducerClass(Reduce.class); 

conf.setInputFormat(TextInputFormat.class); 
conf.setOutputFormat(TextOutputFormat.class); 

FileInputFormat.setInputPaths(conf, new Path(args[0])); 
FileOutputFormat.setOutputPath(conf, new Path("mapred1")); 

JobClient.runJob(conf); 
+0

Se ve bien. ¿Podría publicar el correo, mapa y reducir clases –

+0

Acabo de actualizar la pregunta con el mapa y reducir las clases, aunque soy nuevo en hadoop y no sé cuál es la clase de correo? Lo hice modificando el ejemplo de WordCount que no creo que incluya esa clase. – user1084563

Respuesta

19

Su problema es que establece la clase Reducir como un combinador

conf.setCombinerClass(Reduce.class); 

combinadores ejecutar en la fase mapa y que necesitan para emitir el mismo tipo de clave/valor (IntWriteable, IntWritable en su caso) elimine esta línea y que debe estar bien

+0

hmm, lo intentaré en un momento y veré si funciona, solo lo hice porque esa línea está en el ejemplo de WordCount y tengo otros trabajos de reducción de mapas que han usado eso y no tuve ningún problema. – user1084563

+0

Todavía no se ha ejecutado, pero definitivamente superó el problema que tenía. Respuesta aceptada Solo una cosa, ¿por qué se usa en el ejemplo de WordCount en el sitio web de hadoop? – user1084563

+1

El o/p de Mappers y Combiners se alimenta a los Reductores. En el código, el o/p del combinador es Text/IntWritable y la entrada al reductor es IntWritable/IntWritable que no coincide, por lo que el error. Ver este [artículo] (http://philippeadjiman.com/blog/2010/01/14/hadoop-tutorial-series-issue-4-to-use-or-not-to-use-a-combiner/) on por qué combiners. Para resumir, se utilizan para hacer que el corredor de trabajo sea más rápido al hacer que las tareas del mapa trabajen un poco más en los datos disponibles localmente y, por lo tanto, transfieran menos datos a los reductores. –

Cuestiones relacionadas