2011-12-16 9 views
6

Questo può sembrare una domanda stupida, ma non riesco a capire il problema nei miei tipi nel mio codice MapReduce per HadoopClasse tasto sbagliato: il testo non è IntWritable

Come indicato nella domanda il problema è che si tratta di mi aspetto che sia IntScrivibile ma lo sto passando a un oggetto Testo nel collector.collect del riduttore.

La mia configurazione di posti di lavoro ha le seguenti classi di potenza mapper:

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

e le seguenti classi di potenza riduttore:

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

La mia classe di mappatura è la seguente definizione:

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

con la funzione richiesta:

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

E poi viene a mancare quando chiamo:

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

Sono abbastanza nuovo per mappare ridurre, ma tutti i tipi sembrano corrispondere, compila ma poi non riesce su quella linea dicendo che il suo aspetta un IntWritable come chiave per la classe di riduzione. Se è importante sto utilizzando 0,21 versione di Hadoop

Ecco la mia mappa Categoria:

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); 
     } 
    } 
} 

e la mia classe di ridurre:

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); 
    } 
} 

e la mia configurazione del processo:

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

Sembra buono. Potresti postare la posta, mappare e ridurre le classi –

+0

Appena aggiornato la domanda con la mappa e ridurre le classi, anche se sono nuovo di hasadoop e non so cosa sia la classe mail? Ho fatto questo modificando l'esempio di WordCount che non penso includesse quella classe. – user1084563

risposta

19

Il problema è che si imposta la classe Riduci come combinatore

conf.setCombinerClass(Reduce.class); 

Addizionatore eseguiti in fase di mappa e hanno bisogno di emettere lo stesso tipo di chiave/valore (IntWriteable, IntWritable nel tuo caso) rimuovere questa riga e si dovrebbe essere ok

+0

hmm, ci proverò tra un attimo e vedrò se funziona, l'ho fatto solo perché quella linea è nell'esempio WordCount e ho un'altra mappa che riduce i lavori che l'hanno usata e non ho avuto problemi. – user1084563

+0

Non ha ancora finito di funzionare ma sicuramente ha superato il problema che stavo avendo. Risposta accettata Solo una cosa però, perché viene utilizzata nell'esempio WordCount sul sito web di hadoop? – user1084563

+1

L'o/p di Mappers e Combiners viene inviato a Reducers. Nel codice l'o/p del combinatore è Text/IntWritable e l'input per il riduttore è IntWritable/IntWritable che non corrisponde, quindi l'errore. Vedi questo [articolo] (http://philippeadjiman.com/blog/2010/01/14/hadoop-tutorial-series-issue-4-to-use-or-not-to-use-a-combiner/) su perché combinatori. Per riassumere, vengono utilizzati per rendere più rapido il job runner facendo in modo che le attività della mappa eseguano un po 'più lavoro sui dati disponibili localmente e quindi trasferiscano meno dati ai riduttori. –

Problemi correlati