2013-03-31 11 views
8

Mein Mapper muss senden die folgenden Tupel senden:Wie Java Hadoop Mapper können mehrere Werte

<custID,prodID,rate> 

Und ich will die CustID als Schlüssel zum Minderer senden, und als Wert der prodID und Geschwindigkeit zusammen, wie Sie werden für die Reduktionsphase benötigt. Welches ist der beste Weg, dies zu tun?

public void map(Object key, Text value, Context context) 
     throws IOException, InterruptedException { 

    String[] col = value.toString().split(","); 
    custID.set(col[0]); 
    data.set(col[1] + "," + col[2]); 
    context.write(custID, data); 
} 

public void reduce(Text key, Iterable<Text> values, Context context) 
     throws IOException, InterruptedException { 

    for (Text val : values) { 
     String[] temp = val.toString().split(","); 
     Text rate = new Text(temp[1]); 
     result.set(rate); 
     context.write(key, result); 
    } 
} 
+0

Warum können Sie nicht einfach mehrere Werte senden? Nichts begrenzt die Anzahl der Schlüssel-Wert-Paare, die eine einzelne Map-Aufgabe erzeugen kann. – kichik

Antwort

3

Die einfachste ich denken kann, ist sie nur in einem einzigen String zu fusionieren:

output.collect(custID, prodID + "," + rate); 

Dann teilen, wenn wieder nach oben auf die Reduzierungen.

Wenn Sie etwas mehr Code von Ihrem Mapper posten, könnten wir vielleicht ein besseres Beispiel geben.

UPDATE: Das heißt, Sie fragten nach der besten Weg. Der korrekteste Weg ist wahrscheinlich, eine separate Klassengruppierung prodID und rate zusammen zu erstellen und diese zu senden.

+0

Ich versuche diese Lösung (um sie zusammenzuführen), aber wenn ich in Reduzierer bin, verwende ich String v = val.toString(). Split (","); Befehl, um die Zeichenfolge zu teilen, kann ich die v [0] regelmäßig verwenden, aber wenn ich v [1] -Wert verwenden, bekomme ich eine Ausnahme "Array außerhalb der Grenzen". –

+0

Können Sie etwas Code (in Ihre ursprüngliche Frage oder einen Pastebin/Github-Gist) für das, was Sie derzeit haben, posten? –

+0

Ich habe Code hinzugefügt, danke. –

11

Der beste Weg ist CustomWritables

Dies ist für den doppelten Wert zu schreiben. Sie können, dass

import java.io.DataInput; 
import java.io.DataOutput; 
import java.io.IOException; 
import org.apache.hadoop.io.Writable; 


/** 
* @author Unmesha SreeVeni U.B 
* 
*/ 
public class TwovalueWritable implements Writable { 
    private double first; 
    private double second; 

    public TwovalueWritable() { 
     set(first, second); 
    } 
    public TwovalueWritable(double first, double second) { 
     set(first, second); 
    } 
    public void set(double first, double second) { 
     this.first = first; 
     this.second = second; 
    } 
    public double getFirst() { 
     return first; 
    } 
    public double getSecond() { 
     return second; 
    } 
    @Override 
    public void write(DataOutput out) throws IOException { 
     out.writeDouble(first); 
     out.writeDouble(second); 
    } 
    @Override 
    public void readFields(DataInput in) throws IOException { 
     first = in.readDouble(); 
     second = in.readDouble(); 
    } 

    /* (non-Javadoc) 
    * @see java.lang.Object#hashCode() 
    */ 
    @Override 
    public int hashCode() { 
     final int prime = 31; 
     int result = 1; 
     long temp; 
     temp = Double.doubleToLongBits(first); 
     result = prime * result + (int) (temp^(temp >>> 32)); 
     temp = Double.doubleToLongBits(second); 
     result = prime * result + (int) (temp^(temp >>> 32)); 
     return result; 
    } 
    /* (non-Javadoc) 
    * @see java.lang.Object#equals(java.lang.Object) 
    */ 
    @Override 
    public boolean equals(Object obj) { 
     if (this == obj) { 
      return true; 
     } 
     if (obj == null) { 
      return false; 
     } 
     if (!(obj instanceof TwovalueWritable)) { 
      return false; 
     } 
     TwovalueWritable other = (TwovalueWritable) obj; 
     if (Double.doubleToLongBits(first) != Double 
       .doubleToLongBits(other.first)) { 
      return false; 
     } 
     if (Double.doubleToLongBits(second) != Double 
       .doubleToLongBits(other.second)) { 
      return false; 
     } 
     return true; 
    } 
    @Override 
    public String toString() { 
     return first + "," + second; 
    } 
} 

in Text oder String ändern Und von Mapper können Sie es einfach als

context.write(key,new TwovalueWritable(prodID,rate)); 

Hoffnung ausstrahlen, das hilft.

+0

seine gute Lösungen, aber ich stach-up mit String wie Override-Methode überschreiben ... –

+0

@RaviHTapela: Wenn Sie Eclipse IDE - gleich verwenden, kann HashCode automatisch generiert werden –

Verwandte Themen