2011-05-25 86 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类中定义的方式(您可能会覆盖其实现)。

相关问题