一個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/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 第五章 Vlookup函式示例-細節決定成敗函式
- 《細節決定成敗》 汪中求著
- Java集合詳解8:Java集合類細節精講,細節決定成敗Java
- 邦芒簡歷:求職簡歷細節決定成敗求職
- 熟悉海外客戶區域特點,細節決定成敗!
- 細節決定成敗,淺析《合金彈頭》的成功之道
- 開發者談F2P模式:細節決定成敗模式
- 細節決定成敗,不容忽視的10道Node面試題面試題
- 【2024-03-06】細節成敗
- MapReduce之自定義OutputFormatORM
- MapReduce之自定義InputFormatORM
- MapReduce關於key的定義、hashCode()、equals(Object obj)、compareTo(CustomCombineKey other)Object
- AutoCAD 2024:細節決定成敗,精準設計從這裡開始 mac/win啟用版Mac
- MapReduce之自定義分割槽器Partitioner
- MapReduce 程式設計模型 & WordCount 示例程式設計模型
- 黑猴子的家:HBase 自定義HBase-MapReduce案列一
- 一個 key 能儲存多個 value 的 map --- 自定義的 MultiValueMap,實現 Map 介面
- 穩定幣——決定公鏈成敗的關鍵
- Flutter | 超詳細教你如何自定義一個 Stepper 步驟元件Flutter元件
- 簡單-定義一個小程式元件元件
- Android 自定義View:深入理解自定義屬性(七)AndroidView
- KingbaseES 自定義運算子使用示例
- 自定義一個kaniko映象
- rubymine設定自定義快捷程式碼片段
- laravel8統一介面返回的json格式—通過自定義函式及自定義exception返回成功及失敗結果LaravelJSON函式Exception
- Obsidian自定義程式碼塊樣式成Typora
- 前端定義一個物件的時候,key值如何設定為數字,並抽成常量前端物件
- 自定義有多個按鈕節點的SliderViewIDEView
- 使用joinjs繪製流程圖(六)-自定義節點成html元素JS流程圖HTML
- celery筆記七之週期/定時任務及crontab定義筆記
- 手寫一個自定義PromisePromise
- 自定義一個事件聚合器事件
- 【微信小程式】常用元件及自定義元件微信小程式元件
- SpringBoot?整合mongoDB並自定義連線池的示例程式碼Spring BootMongoDB
- 聊聊Dubbo(七):自定義Filter實踐Filter
- MapReduce 示例:減少 Hadoop MapReduce 中的側連線Hadoop
- Laravel 的一個命名細節分享Laravel
- 一個小的技術細節
- XML Schema 複雜元素型別詳解:定義及示例解析XML型別