TextInputFormat
答えを見つけるには、 の実装を理解する必要があります。
コードに飛び込みましょう。新しい mapreduce API について話しますが、「古い」mapred API は非常に似ています。
あなたが言ったように、ユーザーの観点からは、TextInputFormat
いくつかの改行文字に従って分割をレコードに分割します。実装を確認しましょう。
クラスがほとんど空であることがわかります。重要な機能は、次のcreateRecord
ように定義されています。InputFormat
@Override
public RecordReader<LongWritable, Text> createRecordReader(
InputSplit split,
TaskAttemptContext context
) {
return new LineRecordReader();
}
一般的な契約では、InputFormat を使用して RecordReader を取得します。内部Mapper
をMapContextImpl
見ると、マッパーが RecordReader のみを使用して次のキーと値を取得していることがわかります。彼は他に何も知りません。
マッパー:
public void run(Context context) throws IOException, InterruptedException {
setup(context);
while (context.nextKeyValue()) {
map(context.getCurrentKey(), context.getCurrentValue(), context);
}
cleanup(context);
}
MapContextImpl:
@Override
public boolean nextKeyValue() throws IOException, InterruptedException {
return reader.nextKeyValue();
}
あなたが提供したこのリンクを注意深く読み直してください。次のことがわかります。
NLinesInputFormat
拡張TextInputFormat
し、オーバーライドのみを行います createRecordReader
。基本的に を使用するのではなくLineReader
、独自の を提供しますRecordReader
。TextInputFormat
階層の上位にある別のクラスではなく、拡張する必要があります。これは、このレベルで行われ、必要になる可能性のあるすべての処理が既に行われているためです (圧縮、分割不可能な形式など)。
NLinesRecordReader
本当の仕事をします。これは、提供された から正しいオフセットでシークinitialize
を取得するために必要なことを行います。また、によって使用されるものと同じものを作成しますInputStream
InputSplit
LineReader
TextInputFormat
- この
nextKeyValue
メソッドでは、3 つの行を取得するために 3 回呼び出されることがわかりますLineReader.readLine()
(さらに、大きすぎるレコード、行末、分割の終わりなどのコーナー ケースを適切に処理するロジックもあります)。
それがあなたを助けることを願っています。重要なのは、API の全体的な設計と、各部分がどのように相互作用するかを理解することです。