Входной порт Mapper-Value в Hadoop

Обычно мы записываем отображение в виде:

public static class Map extends Mapper<**LongWritable**, Text, Text, IntWritable>

Здесь пара ключей ввода-вывода для преобразователя <LongWritable, Text> - насколько я знаю, когда картограф получает входные данные, он проходит по строкам - так что ключ для картографа означает номер строки - пожалуйста, исправьте если я ошибаюсь.

Мой вопрос: если я даю пару ключ-значение ввода для mapper как <Text, Text>, то он дает ошибку

 java.lang.ClassCastException: org.apache.hadoop.io.LongWritable cannot be cast to org.apache.hadoop.io.Text

Обязательно ли вводить пару ключ-значение для ввода ключа в качестве <LongWritable, Text> - если да, то почему? если нет, то в чем причина ошибки? Можете ли вы, пожалуйста, помочь мне понять правильную аргументацию ошибки?

Спасибо заранее.

Ответ 1

Вход в устройство отображения зависит от того, что используется InputFormat. InputFormat отвечает за чтение входящих данных и формирование их в любом формате, который ожидает Mapper. По умолчанию InputFormat TextInputFormat, который расширяет FileInputFormat<LongWritable, Text>.

Если вы не меняете InputFormat, используйте Mapper с различной сигнатурой типа Key-Value, чем <LongWritable, Text> приведет к этой ошибке. Если вы ожидаете ввода <Text, Text>, вам нужно будет выбрать подходящий InputFormat. Вы можете установить InputFormat в настройке Job:

job.setInputFormatClass(MyInputFormat.class);

И, как я уже сказал, по умолчанию этот параметр установлен в TextInputFormat.

Теперь скажем, что ваши входные данные представляют собой группу разделенных новой строкой записей, разделенных запятой:

  • "A, value1"
  • "В, значение2"

Если вы хотите, чтобы клавиша ввода отображалась на карте ( "A", "value1" ), ( "B", "value2" ), вам придется реализовать пользовательский InputFormat и RecordReader с подписью <Text, Text>. К счастью, это довольно просто. Существует пример здесь и, возможно, несколько примеров, плавающих вокруг StackOverflow.

Короче говоря, добавьте класс, который расширяет FileInputFormat<Text, Text> и класс, который расширяет RecordReader<Text, Text>. Переопределите метод FileInputFormat#getRecordReader и верните экземпляр своего пользовательского RecordReader.

Затем вам придется реализовать требуемую логику RecordReader. Самый простой способ сделать это - создать экземпляр LineRecordReader в вашем пользовательском RecordReader и делегировать все основные обязанности этому экземпляру. В методах getCurrentKey и getCurrentValue вы реализуете логику для извлечения текстового содержимого с разделителями-запятыми, вызывая LineRecordReader#getCurrentValue и разбивая его на запятую.

Наконец, установите новый InputFormat как Job InputFormat, как показано после второго абзаца выше.

Ответ 2

В книге "Hadoop: The Difinitive Guide" Тома Уайта я думаю, что у него есть соответствующий ответ на это (стр. 197):

"TextInputFormats ключи, являющиеся просто смещением внутри файла, обычно не очень полезно. Обычно каждая строка в файле является пар ключ-значение, разделенная разделителем такой как символ табуляции. Например, это результат, созданный TextOutputFormat, Hadoops default Выходной формат. Чтобы правильно интерпретировать такие файлы, KeyValueTextInputFormat  подходит.

Вы можете указать разделитель через key.value.separator.in.input.line  имущество. Это по умолчанию используется символ табуляции.

Ответ 3

Ключ для ввода Mapper всегда будет типом Integer.... клавиша ввода карты отображает смещение линии no. и значения указывают на всю строку...... записывающее устройство считывает одну строку в первом цикле. И o/p преобразователя может быть любым, что захочет (это может быть (текст, текст) или (текст, встроенный) или......)