通常、マッパーは次の形式で記述します。
public static class Map extends Mapper<**LongWritable**, Text, Text, IntWritable>
ここで、マッパーの入力Key-Valueペアは<LongWritable, Text>
です-マッパーが入力データを取得すると、行ごとに入力データを取得します-したがって、マッパーのキーは行番号を示します-修正してください私が間違っている場合。
私の質問は、マッパーの入力キーと値のペアを<Text, Text>
として指定すると、エラーが発生します
Java.lang.ClassCastException: org.Apache.hadoop.io.LongWritable cannot be cast to org.Apache.hadoop.io.Text
マッパーの入力Key-Valueペアを<LongWritable, Text>
として指定することは必須ですか?はいの場合、なぜですか?いいえの場合、エラーの理由は何ですか?エラーの適切な理由を教えてください。
前もって感謝します。
マッパーへの入力は、使用されるInputFormatによって異なります。 InputFormatは、着信データを読み取り、マッパーが期待する形式に整形します。デフォルトのInputFormatは TextInputFormat で、FileInputFormat<LongWritable, Text>
を拡張します。
InputFormatを変更しない場合、<LongWritable, Text>
とは異なるKey-Valueタイプシグネチャを持つマッパーを使用すると、このエラーが発生します。 <Text, Text>
入力が必要な場合は、適切なInputFormatを選択する必要があります。ジョブの設定でInputFormatを設定できます。
job.setInputFormatClass(MyInputFormat.class);
そして、私が言ったように、これはデフォルトでTextInputFormatに設定されています。
ここで、入力データが、コンマで区切られた改行で区切られた一連のレコードであるとします。
マッパーへの入力キーを( "A"、 "value1")、( "B"、 "value2")にする場合は、<Text, Text>
シグネチャを使用してカスタムInputFormatおよびRecordReaderを実装する必要があります。 幸いにも、これはかなり簡単です。 ここの例 があり、おそらくいくつかの例もStackOverflowの周りに浮かんでいます。
つまり、FileInputFormat<Text, Text>
を拡張するクラスとRecordReader<Text, Text>
を拡張するクラスを追加します。 FileInputFormat#getRecordReader
メソッドをオーバーライドして、カスタムRecordReaderのインスタンスを返すようにします。
次に、必要なRecordReaderロジックを実装する必要があります。これを行う最も簡単な方法は、カスタムRecordReaderに LineRecordReader のインスタンスを作成し、すべての基本的な責任をこのインスタンスに委任することです。 getCurrentKeyメソッドとgetCurrentValueメソッドでは、LineRecordReader#getCurrentValue
を呼び出してコンマで区切られたテキストコンテンツを抽出し、コンマで分割するロジックを実装します。
最後に、上記の2番目の段落の後に示すように、新しいInputFormatをJob InputFormatとして設定します。
トムホワイトの本「Hadoop:The Difinitive Guide」では、彼はこれに対して適切な答えを持っていると思います(197ページ)。
「TextInputFormatのキーは、単にファイル内のオフセットであるため、通常はあまり役に立ちません。ファイル内の各行が、タブ文字などの区切り文字で区切られたキーと値のペアであることが一般的です。たとえば、これはTextOutputFormatによって生成された出力、HadoopのデフォルトのOutputFormatこのようなファイルを正しく解釈するには、KeyValueTextInputFormatが適切です。
Key.value.separator.in.input.lineプロパティを介してセパレータを指定できます。デフォルトではタブ文字です。」