一個MapReduce 程式示例 細節決定成敗(七) :自定義Key 及RecordReader
上一篇中,演示瞭如何使用CombineFileInputFormat 來優化當有多個輸入小檔案時,減少起動的map task個數。
在自定義的MyCombineFileInputFormat中的MyRecordReader是簡單代理了LineRecordReader。
其它我也還可以在這個地方做更多的東西。
本次實驗是使用自定義的RecordReader從split中自定義 key value。
自定義MyKey
Mapper程式程式碼
可以看到使用MyRecordReader返回自定義Key後,Map 函式得到了很大的簡化。
為了方便以後檢視,把主程式程式碼也貼上來。
而且使用自定義的MyRecordReader的好處不限於此,稍後一篇討論使用TotalOrderPartitioner時會發現,對於詞頻統計,使用TotalOrderPartitioner 自定義RecordReader是必要的。
在自定義的MyCombineFileInputFormat中的MyRecordReader是簡單代理了LineRecordReader。
其它我也還可以在這個地方做更多的東西。
本次實驗是使用自定義的RecordReader從split中自定義 key value。
自定義MyKey
自定義的key 需要實現WritableComparable 介面。
點選(此處)摺疊或開啟
-
package wordcount;
-
-
import java.io.DataInput;
-
import java.io.DataOutput;
-
import java.io.IOException;
-
-
import org.apache.hadoop.io.WritableComparable;
-
-
public class MyKey implements WritableComparable<MyKey> {
-
-
private char c;
-
@Override
-
public void write(DataOutput out) throws IOException {
-
out.writeChar(c);
-
}
-
-
@Override
-
public void readFields(DataInput in) throws IOException {
-
c= in.readChar();
-
}
-
-
@Override
-
public int compareTo(MyKey key) {
-
if(c==key.c)
-
return 0;
-
else if(c> key.c)
-
return 1;
-
else
-
return -1;
-
}
-
-
public char getC() {
-
return c;
-
}
-
-
public void setC(char c) {
-
this.c = c;
-
}
-
-
- }
自定義CombinedFilesInputFormat 自定義RecordReader
點選(此處)摺疊或開啟
-
package wordcount;
-
-
import java.io.IOException;
-
-
import org.apache.commons.lang.StringUtils;
-
import org.apache.hadoop.io.IntWritable;
-
import org.apache.hadoop.io.LongWritable;
-
import org.apache.hadoop.io.Text;
-
import org.apache.hadoop.mapreduce.InputSplit;
-
import org.apache.hadoop.mapreduce.RecordReader;
-
import org.apache.hadoop.mapreduce.TaskAttemptContext;
-
import org.apache.hadoop.mapreduce.lib.input.CombineFileInputFormat;
-
import org.apache.hadoop.mapreduce.lib.input.CombineFileRecordReader;
-
import org.apache.hadoop.mapreduce.lib.input.CombineFileSplit;
-
import org.apache.hadoop.mapreduce.lib.input.FileSplit;
-
import org.apache.hadoop.mapreduce.lib.input.LineRecordReader;
-
import org.apache.log4j.Logger;
-
-
-
public class MyCombinedFilesInputFormat extends CombineFileInputFormat<LongWritable, Text> {
-
-
@SuppressWarnings({ "unchecked", "rawtypes" })
-
@Override
-
public RecordReader<LongWritable, Text> createRecordReader(InputSplit split, TaskAttemptContext context) throws IOException {
-
return new CombineFileRecordReader((CombineFileSplit) split,context,MyCombinedFilesRecordReader.class);
-
}
-
-
public static class MyCombinedFilesRecordReader extends RecordReader<MyKey, IntWritable> {
-
private int index;
-
private LineRecordReader reader;
-
-
private String tValue;
-
private int pos=0;
-
-
private MyKey key = new MyKey();
-
-
Logger log = Logger.getLogger(MyCombinedFilesRecordReader.class);
-
public MyCombinedFilesRecordReader(CombineFileSplit split, TaskAttemptContext context, Integer index) {
-
this.index = index;
-
reader = new LineRecordReader();
-
}
-
-
@Override
-
public void initialize(InputSplit split, TaskAttemptContext context)
-
throws IOException, InterruptedException {
-
CombineFileSplit cfsplit = (CombineFileSplit) split;
-
FileSplit fileSplit = new FileSplit(cfsplit.getPath(index),
-
cfsplit.getOffset(index),
-
cfsplit.getLength(index),
-
cfsplit.getLocations()
-
);
-
reader.initialize(fileSplit, context);
-
}
-
-
@Override
-
public boolean nextKeyValue() throws IOException, InterruptedException {
-
if(StringUtils.isEmpty(tValue)||pos>=tValue.length()-1){
-
if(reader.nextKeyValue()){
-
pos = 0;
-
this.tValue = reader.getCurrentValue().toString();
-
return true;
-
}
-
else{
-
return false;
-
}
-
}
-
else{
-
pos ++;
-
if(tValue.charAt(pos)<='z' && tValue.charAt(pos)>='A'){
-
return true;
-
}
-
else{
-
return nextKeyValue();
-
}
-
}
-
}
-
-
@Override
-
public MyKey getCurrentKey() throws IOException,
-
InterruptedException {
-
key.setC(tValue.charAt(pos));
-
return key;
-
}
-
-
@Override
-
public IntWritable getCurrentValue() throws IOException, InterruptedException {
-
return new IntWritable(1);
-
}
-
-
@Override
-
public float getProgress() throws IOException, InterruptedException {
-
return reader.getProgress();
-
}
-
-
@Override
-
public void close() throws IOException {
-
reader.close();
-
}
-
-
}
- }
可以看到使用MyRecordReader返回自定義Key後,Map 函式得到了很大的簡化。
點選(此處)摺疊或開啟
-
public static class MyWordCountMapper extends
-
Mapper<MyKey, NullWritable, Text, IntWritable> {
-
Text mKey = new Text();
-
IntWritable mValue = new IntWritable(1);
-
@Override
-
protected void map(MyKey key, NullWritable value, Context context)
-
throws IOException, InterruptedException {
-
mKey.set(String.valueOf(key.getC()));
-
context.write(mKey, mValue);
-
}
- }
點選(此處)摺疊或開啟
-
package wordcount;
-
-
import java.io.IOException;
-
-
import org.apache.hadoop.conf.Configuration;
-
import org.apache.hadoop.conf.Configured;
-
import org.apache.hadoop.fs.Path;
-
import org.apache.hadoop.io.IntWritable;
-
import org.apache.hadoop.io.NullWritable;
-
import org.apache.hadoop.io.Text;
-
import org.apache.hadoop.mapreduce.Job;
-
import org.apache.hadoop.mapreduce.Mapper;
-
import org.apache.hadoop.mapreduce.Reducer;
-
import org.apache.hadoop.mapreduce.lib.input.TextInputFormat;
-
import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat;
-
import org.apache.hadoop.util.Tool;
-
import org.apache.hadoop.util.ToolRunner;
-
import org.apache.log4j.Logger;
-
-
public class MyWordCountJob extends Configured implements Tool {
-
Logger log = Logger.getLogger(MyWordCountJob.class);
-
-
public static class MyWordCountMapper extends
-
Mapper<MyKey, NullWritable, Text, IntWritable> {
-
Text mKey = new Text();
-
IntWritable mValue = new IntWritable(1);
-
@Override
-
protected void map(MyKey key, NullWritable value, Context context)
-
throws IOException, InterruptedException {
-
mKey.set(String.valueOf(key.getC()));
-
context.write(mKey, mValue);
-
}
-
}
-
-
public static class MyWordCountReducer extends Reducer<Text, IntWritable, Text, IntWritable> {
-
Text rkey = new Text();
-
IntWritable rvalue = new IntWritable(1);
-
@Override
-
protected void reduce(Text key, Iterable<IntWritable> values,Context context)
-
throws IOException, InterruptedException {
-
-
int n=0;
-
for(IntWritable value :values){
-
n+= value.get();
-
}
-
rvalue.set(n);
-
context.write(key, rvalue);
-
}
-
}
-
-
@Override
-
public int run(String[] args) throws Exception {
-
//valid the parameters
-
if(args.length !=2){
-
return -1;
-
}
-
-
Job job = Job.getInstance(getConf(), "MyWordCountJob");
-
job.setJarByClass(MyWordCountJob.class);
-
-
Path inPath = new Path(args[0]);
-
Path outPath = new Path(args[1]);
-
-
outPath.getFileSystem(getConf()).delete(outPath,true);
-
TextInputFormat.setInputPaths(job, inPath);
-
TextOutputFormat.setOutputPath(job, outPath);
-
-
-
job.setMapperClass(MyWordCountJob.MyWordCountMapper.class);
-
job.setReducerClass(MyWordCountJob.MyWordCountReducer.class);
-
-
job.setInputFormatClass(MyCombinedFilesInputFormat.class);
-
MyCombinedFilesInputFormat.setMaxInputSplitSize(job, 1024*1024*64);
-
job.setOutputFormatClass(TextOutputFormat.class);
-
job.setMapOutputKeyClass(Text.class);
-
job.setMapOutputValueClass(IntWritable.class);
-
job.setOutputKeyClass(Text.class);
-
job.setOutputValueClass(IntWritable.class);
-
-
-
return job.waitForCompletion(true)?0:1;
-
}
-
public static void main(String [] args){
-
int result = 0;
-
try {
-
result = ToolRunner.run(new Configuration(), new MyWordCountJob(), args);
-
} catch (Exception e) {
-
e.printStackTrace();
-
}
-
System.exit(result);
-
}
-
- }
而且使用自定義的MyRecordReader的好處不限於此,稍後一篇討論使用TotalOrderPartitioner時會發現,對於詞頻統計,使用TotalOrderPartitioner 自定義RecordReader是必要的。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/30066956/viewspace-2109264/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 一個MapReduce 程式示例 細節決定成敗(一)
- 一個MapReduce 程式示例 細節決定成敗(五) :Partitioner
- 一個MapReduce 程式示例 細節決定成敗(九):RawComparator
- 一個MapReduce 程式示例 細節決定成敗(八):TotalOrderPartitioner
- 一個MapReduce 程式示例 細節決定成敗(二) :觀察日誌及 Counter
- 一個MapReduce 程式示例 細節決定成敗(六) :CombineFileInputFormatORM
- 一個MapReduce 程式示例 細節決定成敗(三) :Combiner
- 細節決定成敗 MapReduce任務實戰 Map Join
- 細節決定成敗 MapReduce任務實戰 Reduce Join
- 細節決定成敗 MapReduce任務實戰 倒排索引索引
- 第五章 Vlookup函式示例-細節決定成敗函式
- 細節決定成敗!APP設計不容忽視的20個細節APP
- 如何讓程式設計師幸福工作:細節決定成敗程式設計師
- 面試:黃金法則——細節決定成敗面試
- Java集合詳解8:Java集合類細節精講,細節決定成敗Java
- 開發者談F2P模式:細節決定成敗模式
- 邦芒簡歷:求職簡歷細節決定成敗求職
- Python讀書筆記:細節決定成敗(2)Python筆記
- Python讀書筆記:細節決定成敗(1)Python筆記
- 汪峰FIIL Diva智慧耳機究竟如何?細節決定成敗
- 細節決定ERP專案啟動會的成敗
- 細節決定成敗,不容忽視的10道Node面試題面試題
- 細節決定成敗——無CSS時網頁的可讀性CSS網頁
- 軟體設計是怎樣煉成的(7)——細節決定成敗(詳細設計)
- AngularJS 自定義 Directive 及程式碼示例AngularJS
- MapReduce之自定義OutputFormatORM
- MapReduce之自定義InputFormatORM
- MapReduce之自定義partitioner
- 【原創】構建高效能ASP.NET站點之三 細節決定成敗ASP.NET
- 一個簡單的MapReduce示例(多個MapReduce任務處理)
- 【2024-03-06】細節成敗
- MapReduce程式設計例項之自定義排序程式設計排序
- 決定開發者面試成敗的 3 個問題面試
- MapReduce程式設計例項之自定義分割槽程式設計
- MapReduce關於key的定義、hashCode()、equals(Object obj)、compareTo(CustomCombineKey other)Object
- MapReduce之自定義分割槽器Partitioner
- JavaScript初學者應注意的七個細節JavaScript
- AutoCAD 2024:細節決定成敗,精準設計從這裡開始 mac/win啟用版Mac