Сериализация с использованием ArrayWritable выглядит забавно

Я работал с ArrayWritableВ какой-то момент мне нужно было проверить, как Hadoop сериализует ArrayWritableэто то, что я получил, установив job.setNumReduceTasks(0):

0    IntArrayWritable@10f11b8
3    IntArrayWritable@544ec1
6    IntArrayWritable@fe748f
8    IntArrayWritable@1968e23
11    IntArrayWritable@14da8f4
14    IntArrayWritable@18f6235

и это тестовый маппер, который я использовал:

public static class MyMapper extends Mapper<LongWritable, Text, LongWritable, IntArrayWritable> {

    public void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
        int red = Integer.parseInt(value.toString());
        IntWritable[] a = new IntWritable[100];

        for (int i =0;i<a.length;i++){
            a[i] = new IntWritable(red+i);
        }

        IntArrayWritable aw = new IntArrayWritable();
        aw.set(a);
        context.write(key, aw);
    }
}

IntArrayWritable взято из примера, приведенного в javadoc: ArrayWritable.

import org.apache.hadoop.io.ArrayWritable;
import org.apache.hadoop.io.IntWritable;

public class IntArrayWritable extends ArrayWritable {
    public IntArrayWritable() {
        super(IntWritable.class);
    }
}

Я на самом деле проверил исходный код Hadoop, и это не имеет смысла для меня.ArrayWritable не следует сериализовать имя класса и нет никакого способа, чтобы массив из 100 IntWritable можно сериализовать с использованием шестнадцатеричных значений 6/7. Приложение на самом деле работает нормально, а редуктор десериализует правильные значения... Что происходит? Что мне не хватает?

4 ответа

Решение

Проблема в том, что вывод, который вы получаете из задания MapReduce, не является сериализованной версией этих данных. Это то, что переводится в красивую печатную строку.

Когда вы устанавливаете число редукторов на ноль, ваши преобразователи теперь проходят через выходной формат, который отформатирует ваши данные, вероятно, преобразовав их в читаемую строку. Он не выводит его серийно, как если бы его собирал редуктор.

Вы должны переопределить значение по умолчанию toString() метод.

Это называется TextOutputFormat создать читабельный формат.

Попробуйте следующий код и посмотрите результат:

public class IntArrayWritable extends ArrayWritable {
    public IntArrayWritable() {
        super(IntWritable.class);
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        for (String s : super.toStrings())
        {
            sb.append(s).append(" ");
        }
        return sb.toString();
    }
}

Вы смотрели в SequenceFileInputFormat и SequenceFileOutputFormat? Вы можете настроить их с помощью:

job.setInputFormatClass(SequenceFileInputFormat.class); 

а также

job.setOutputFormatClass(TextOutputFormat.class);

Это очень просто. Hadoop использует метод write (DataOutput out) для записи объекта в сериализованную версию (для получения дополнительной информации см. Документ документа hadoop ArrayWritable). Когда вы расширяете ArrayWritable с помощью IntArrayWritable, ваш собственный класс будет использовать эти методы из унаследованного класса. До свидания.

Другие вопросы по тегам