2011-05-25 87 views
5

單個Mapper類可以在單次運行中生成多個鍵值對(相同類型)嗎?Hadoop映射器可以在輸出中生成多個鍵嗎?

我們輸出的鍵值對的映射是這樣的:

context.write(key, value); 

這是關鍵的下調(與爲例)版本:

import java.io.DataInput; 
import java.io.DataOutput; 
import java.io.IOException; 

import org.apache.hadoop.io.ObjectWritable; 
import org.apache.hadoop.io.WritableComparable; 
import org.apache.hadoop.io.WritableComparator; 


public class MyKey extends ObjectWritable implements WritableComparable<MyKey> { 

    public enum KeyType { 
     KeyType1, 
     KeyType2 
    } 

    private KeyType keyTupe; 
    private Long field1; 
    private Integer field2 = -1; 
    private String field3 = ""; 


    public KeyType getKeyType() { 
     return keyTupe; 
    } 

    public void settKeyType(KeyType keyType) { 
     this.keyTupe = keyType; 
    } 

    public Long getField1() { 
     return field1; 
    } 

    public void setField1(Long field1) { 
     this.field1 = field1; 
    } 

    public Integer getField2() { 
     return field2; 
    } 

    public void setField2(Integer field2) { 
     this.field2 = field2; 
    } 


    public String getField3() { 
     return field3; 
    } 

    public void setField3(String field3) { 
     this.field3 = field3; 
    } 

    @Override 
    public void readFields(DataInput datainput) throws IOException { 
     keyTupe = KeyType.valueOf(datainput.readUTF()); 
     field1 = datainput.readLong(); 
     field2 = datainput.readInt(); 
     field3 = datainput.readUTF(); 
    } 

    @Override 
    public void write(DataOutput dataoutput) throws IOException { 
     dataoutput.writeUTF(keyTupe.toString()); 
     dataoutput.writeLong(field1); 
     dataoutput.writeInt(field2); 
     dataoutput.writeUTF(field3); 
    } 

    @Override 
    public int compareTo(MyKey other) { 
     if (getKeyType().compareTo(other.getKeyType()) != 0) { 
      return getKeyType().compareTo(other.getKeyType()); 
     } else if (getField1().compareTo(other.getField1()) != 0) { 
      return getField1().compareTo(other.getField1()); 
     } else if (getField2().compareTo(other.getField2()) != 0) { 
      return getField2().compareTo(other.getField2()); 
     } else if (getField3().compareTo(other.getField3()) != 0) { 
      return getField3().compareTo(other.getField3()); 
     } else { 
      return 0; 
     } 
    } 

    public static class MyKeyComparator extends WritableComparator { 
     public MyKeyComparator() { 
      super(MyKey.class); 
     } 

     public int compare(byte[] b1, int s1, int l1, byte[] b2, int s2, int l2) { 
      return compareBytes(b1, s1, l1, b2, s2, l2); 
     } 
    } 

    static { // register this comparator 
     WritableComparator.define(MyKey.class, new MyKeyComparator()); 
    } 
} 

這就是我們如何努力在映射器中輸出兩個鍵:

MyKey key1 = new MyKey(); 
key1.settKeyType(KeyType.KeyType1); 
key1.setField1(1L); 
key1.setField2(23); 

MyKey key2 = new MyKey(); 
key2.settKeyType(KeyType.KeyType2); 
key2.setField1(1L); 
key2.setField3("abc"); 

context.write(key1, value1); 
context.write(key2, value2); 

我們的作業的輸出格式類是:org.apache.hadoop.mapr educe.lib.output.SequenceFileOutputFormat

我指出這一點,因爲在其他的輸出格式班是我見過的輸出不追加,只是在執行寫入方法的承諾。

而且,我們正在使用的映射以下類和語境:多次 org.apache.hadoop.mapreduce.Mapper org.apache.hadoop.mapreduce.Context

+0

不確定「type」是什麼意思。你問你是否可以獲得與多個值相關聯的相同密鑰或者多次生成具有相同值的相同密鑰? – diliop 2011-05-25 17:20:46

+0

我想要映射器的單次運行輸出每個具有不同值的兩個鍵。 – 2011-05-25 17:24:58

+0

肯定這是可能的,這實際上是正確的做事方式。 – 2011-05-25 17:56:44

回答

10

寫上下文在一個地圖任務非常好。

但是,您的關鍵類可能有幾個問題。每當您爲某個密鑰實施WritableComparable時,還應該執行equals(Object)hashCode()方法。這些不是WritableComparable接口的一部分,因爲它們在Object中定義,但必須提供實現。

默認分區程序使用hashCode()方法來確定每個鍵/值對要傳遞給哪個reducer。如果你沒有提供一個合理的實現,你可能會得到奇怪的結果。根據經驗法則,無論何時執行hashCode()或任何類型的比較方法,您都應該提供一個equals(Object)方法。您必須確保它接受Object作爲參數,因爲它是在Object類中定義的方式(您可能會覆蓋其實現)。

相關問題