Может ли Hadoop mapper генерировать несколько ключей на выходе? - PullRequest
5 голосов
/ 25 мая 2011

Может ли один класс Mapper создавать несколько пар ключ-значение (одного типа) за один прогон?

Мы выводим пару ключ-значение в маппере следующим образом:

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

И вот как мы пытались вывести обе клавиши в Mapper:

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.mapreduce.lib.output.SequenceFileOutputFormat

Я утверждаю это, потому что в других классах выходного формата я видел, что вывод не добавляется и просто фиксируется в их реализации записиmethod.

Мы также используем следующие классы для Mapper и Context: org.apache.hadoop.mapreduce.Mapper org.apache.hadoop.mapreduce.Context

1 Ответ

10 голосов
/ 26 мая 2011

Многократная запись в контекст в одной задаче карты.

Однако у вас может быть несколько проблем с вашим классом ключей.Всякий раз, когда вы реализуете WritableComparable для ключа, вы также должны реализовывать equals(Object) и hashCode() методы.Они не являются частью интерфейса WritableComparable, так как они определены в Object, но вы должны предоставить реализации.

Разделитель по умолчанию использует метод hashCode(), чтобы решить, какой редуктор подходит для каждой пары ключ / значение.к.Если вы не предоставляете разумную реализацию, вы можете получить странные результаты.

Как правило, всякий раз, когда вы реализуете hashCode() или любой другой метод сравнения, вы должны предоставить метод equals(Object) какЧто ж.Вам нужно убедиться, что он принимает Object в качестве параметра, так как он определен в классе Object (чья реализация вы, вероятно, переопределяете).

...