InputFormat是MapReduce中一個很常用的概念,它在程序的運行中到底起到了什麼作用呢?
InputFormat其實是一個接口,包含了兩個方法:
public interface InputFormat<K, V> {
InputSplit[]getSplits(JobConf job, int numSplits) throws IOException;
RecordReader<K, V>getRecordReader(InputSplit split,
JobConf job,
Reporter reporter) throws IOException;
}
這兩個方法有分別完成著以下工作:
方法getSplits將輸入數據切分成splits,splits的個數即為map tasks的個數,splits的大小默認為塊大小,即64M
方法getSplits將每個split解析成records, 再依次將record解析成<K,V>對
也就是說InputFormat完成以下工作:
InputFile --> splits--> <K,V>
系統常用的 InputFormat 又有哪些呢?
其中TextInputFormat便是最常用的,它的<K,V>就代表<行偏移,該行內容>
然而系統所提供的這幾種固定的將 InputFile轉換為<K,V>的方式有時候並不能滿足我們的需求:
此時需要我們自定義InputFormat ,從而使Hadoop框架按照我們預設的方式來將
InputFile解析為<K,V>
在領會自定義InputFormat 之前,需要弄懂一下幾個抽象類、接口及其之間的關系:
InputFormat(interface), FileInputFormat(abstract class), TextInputFormat(class),
RecordReader(interface), LineRecordReader(class)的關系
FileInputFormat
implements InputFormat
TextInputFormat
extends FileInputFormat
TextInputFormat.getRecordReader
calls LineRecordReader
LineRecordReader
implements RecordReader
對於InputFormat接口,上面已經有詳細的描述
再看看FileInputFormat,它實現了InputFormat接口中的getSplits方法,而將getRecordReader與isSplitable留給具體類(如TextInputFormat)實現,isSplitable方法通常不用修改,所以只需要在自定義的InputFormat中實現
getRecordReader方法即可,而該方法的核心是調用LineRecordReader(即由LineRecorderReader類來實現 "將每個split解析成records, 再依次將record解析成<K,V>對"),該方法實現了接口RecordReader
public interface RecordReader<K, V> {
booleannext(K key, V value) throws IOException;
KcreateKey();
VcreateValue();
longgetPos() throws IOException;
public voidclose() throws IOException;
floatgetProgress() throws IOException;
}