Сериализация с использованием 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, ваш собственный класс будет использовать эти методы из унаследованного класса. До свидания.