2016-04-16 7 views
0

Ich habe 2 Eingabedateien für eine Hadoop MapRed-Aufgabe.Reducer-Task in Hadoop verhält sich nicht wie erwartet

Die Eingabe in das Programm ist input.txt, die in jeder Zeile enthält PaperID keyword1 keyword2 FieldID

p20 k j f3 
p21 k j f11 
p22 k j f3 
p23 k j f2 
p23 k j f1 

Die Datei sammap.txt in der Reducer Klasse verwendet in jeder Reihe enthält FieldID FieldName

f1 AI 
f2 DB 
f3 DB 
f4 AI 

Der Code lautet wie folgt: paket dorado;

import java.io.BufferedReader; 
import java.io.FileReader; 
import java.io.IOException; 
import java.util.ArrayList; 
import java.util.HashMap; 
import java.util.Iterator; 
import java.util.Map; 
import java.util.Set; 
import java.util.StringTokenizer; 

import org.apache.hadoop.conf.Configuration; 
import org.apache.hadoop.fs.Path; 
import org.apache.hadoop.io.IntWritable; 
import org.apache.hadoop.io.Text; 
import org.apache.hadoop.mapreduce.Job; 
import org.apache.hadoop.mapreduce.Mapper; 
import org.apache.hadoop.mapreduce.Reducer; 
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat; 
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat; 

public class Dorado { 

    public static class TokenizerMapper 
     extends Mapper<Object, Text, Text, Text>{ 

    private Text word = new Text(); 
    public void map(Object key, Text value, Context context) throws IOException, InterruptedException { 
     String str = value.toString().replaceAll(" +", " ").trim(), fir="", lst=""; 
     if (!str.equals("")) { 
      fir = str.substring(0, str.indexOf(" ")); 
      lst = str.substring(str.lastIndexOf(" ")+1); 

      context.write(new Text(fir), new Text(lst)); 
     } 


    } 
    } 

    public static class IntSumReducer 
     extends Reducer<Text,Text,Text,Text> { 
    // private IntWritable result = new IntWritable(); 
    private HashMap<Text, Text> fieldToClass = new HashMap<>(); 
    public void reduce(Text key, Iterable <Text> value,Context context) throws IOException, InterruptedException { 
     FileReader fr = new FileReader("sammap.txt"); 
     BufferedReader br = new BufferedReader(fr); 
     String str=null; 
     while ((str = br.readLine()) != null) { 
      String st[] = str.split(" +"); 
      fieldToClass.put(new Text(st[0].trim()), new Text(st[1].trim())); 

      //System.out.println("--"+st[0].trim()+"--"+ st[1].trim()+"--"); 
     } 
     fr.close(); 

     for (Text field : value) { 
      System.out.println(key + "-->" + field); 

      if (fieldToClass.containsKey(field)) 
       context.write(key, fieldToClass.get(field)); 
     } 

    } 
    } 

    public static void main(String[] args) throws Exception { 
    Configuration conf = new Configuration(); 
    Job job = Job.getInstance(conf, "dorado"); 
    job.setJarByClass(Dorado.class); 
    job.setMapperClass(TokenizerMapper.class); 
    job.setCombinerClass(IntSumReducer.class); 
    job.setReducerClass(IntSumReducer.class); 
    job.setOutputKeyClass(Text.class); 
    job.setOutputValueClass(Text.class); 
    FileInputFormat.addInputPath(job, new Path(args[0])); 
    FileOutputFormat.setOutputPath(job, new Path(args[1])); 
    System.exit(job.waitForCompletion(true) ? 0 : 1); 
    } 
} 

Die HashMap fieldToClass hat den Schlüssel als FieldID und Wert als Feldname.

Die Ausgabe auf der Konsole für das Snippet folgenden Code in der Reducer Klasse:

for (Text field : value) { 
    System.out.println(key + "-->" + field); 
    if (fieldToClass.containsKey(field)) 
     context.write(key, fieldToClass.get(field)); 
} 

ist dies:

p20-->DB 
p22-->DB 
p23-->AI 
p23-->DB 

Allerdings würden wir die Ausgabe des Formulars erwarten:

p20-->f3 
p22-->f3 
p23-->f1 
p23-->f2 

Auch gibt es keine Ausgabe in der endgültigen Ausgabedatei des Programms. Die Datei ist leer.

Die richtige Ausgabe wir in der Datei erwarten ist:

p20 DB 
p22 DB 
p23 DB 
p23 AI 

Warum das Programm fehlerhaft verhalten wird? Was sind die möglichen Lösungen?

+0

Allerdings würden wir erwarten, der Ausgang der Form zu sein: p20 -> f3 p22 -> f3 p23 -> f1 p23 -> f2 Sie sicher sind? –

+0

Ich sehe nicht, warum Sie eine andere Ausgabe mit dem Code bekommen, den Sie gepostet haben. Während Sie einen Schlüssel und alle damit verbundenen Werte drucken, sollten Sie jedes Schlüssel- und Wertepaar erhalten haben, das vom Mapper ausgegeben wurde. Und geben Sie beim Übergeben eines Jobs mit der 'setNumReduceTasks()' -Methode immer explizit die Anzahl der Reduzierungen an. Und wie machst du diesen Job? In lokalen oder in einem Cluster? –

+0

@BurakKarasoy - Ja. Auf der Konsole. Und die Ausgabe für den Reducer auf Kontext wird auch separat in der Frage erwähnt. – dorado

Antwort

1

Ihr gesamter Prozess kann innerhalb des Mappers selbst durchgeführt werden. Verwenden Sie die Setup-Funktion des Mappers, um die HashMap zu initialisieren. Suche direkt nach der fieldId in der HashMap und erhalte dessen Wert und schreibe ihn in den Kontext. Geben Sie das gleiche im Reduzierer innerhalb der for-Schleife des iterablen Wertes aus.

+0

Bitte geben Sie einen Beispielcode ein. – dorado

Verwandte Themen