自定义InputFormat /InputSplit/RecordReader

在编写MapReduce的时候,自带的输入格式有时候满足不了我们的需求,这个时候就要自己来定制InputFprmat、InputSplit和RecordReader。
MapReduce自带的输入类型都是基于HDFS的,这个例子的功能是,不从HDFS上面读取输入内容,在内存中随机生成100个(0-1)float型的小数,然后求这100个小数的最大值。


1、类 FindMaxValueInputFormat  继承抽象类 InputFormat: 
主要实现的方法:
public abstract List<InputSplit> getSplits(JobContext context)


public abstract  RecordReader<K,V> createRecordReader(InputSplit split,TaskAttemptContext context)


  1. package inputformat;  
  2.   
  3.   
  4. import java.io.IOException;  
  5. import java.util.ArrayList;  
  6. import java.util.List;  
  7. import java.util.Random;  
  8.   
  9.   
  10. import org.apache.hadoop.io.ArrayWritable;  
  11. import org.apache.hadoop.io.IntWritable;  
  12. import org.apache.hadoop.mapreduce.InputFormat;  
  13. import org.apache.hadoop.mapreduce.InputSplit;  
  14. import org.apache.hadoop.mapreduce.JobContext;  
  15. import org.apache.hadoop.mapreduce.RecordReader;  
  16. import org.apache.hadoop.mapreduce.TaskAttemptContext;  
  17.   
  18.   
  19. public class FindMaxValueInputFormat extends InputFormat<IntWritable, ArrayWritable>{  
  20.     public static float[] floatvalues;  
  21.     /** 
  22.      * 返回一个InputSplit 集合 
  23.      * 这个例子一共有两个InputSplit,两个map 
  24.      * 随机产生100个 0-1 的数组,放到float数组里面 
  25.      */  
  26.     @Override  
  27.     public List<InputSplit> getSplits(JobContext context) throws IOException,  
  28.             InterruptedException {  
  29.         int NumOfValues = context.getConfiguration().getInt("NumOfValues"100);  
  30.         floatvalues = new float[NumOfValues];  
  31.         Random rand =new Random();  
  32.           
  33.         for (int i = 0; i < NumOfValues; i++) {  
  34.             floatvalues[i]=rand.nextFloat();  
  35.         }  
  36.         int NumSplits = context.getConfiguration().getInt("mapred.map.tasks"2);  
  37.         int beg=0;  
  38.         int length =(int) Math.floor(NumOfValues/NumSplits);  
  39.           
  40.         ArrayList<InputSplit> splits =new ArrayList<InputSplit>();  
  41.         int end = length-1;  
  42.           
  43.         for (int i = 0; i < NumSplits-1; i++) {  
  44.             FindMaxValueInputSplit split =new FindMaxValueInputSplit(beg,end);  
  45.             splits.add(split);  
  46.               
  47.             beg=end+1;  
  48.             end=end+length-1;  
  49.         }  
  50.           
  51.         FindMaxValueInputSplit split=new FindMaxValueInputSplit(beg,NumOfValues-1);  
  52.         splits.add(split);  
  53.           
  54.         return splits;  
  55.     }  
  56.       
  57.     /** 
  58.      * 自定义 RecordReader 
  59.      */  
  60.     @Override  
  61.     public RecordReader<IntWritable, ArrayWritable> createRecordReader(  
  62.             InputSplit split, TaskAttemptContext context) throws IOException,  
  63.             InterruptedException {  
  64.         return new FindMaxValueRecordReader();  
  65.     }  
  66.       
  67. }  




2、类 FindMaxValueInputSplit 继承 InputSplit 实现 Writable :
  1. package inputformat;  
  2.   
  3.   
  4. import java.io.DataInput;  
  5. import java.io.DataOutput;  
  6. import java.io.IOException;  
  7.   
  8.   
  9. import org.apache.hadoop.io.ArrayWritable;  
  10. import org.apache.hadoop.io.FloatWritable;  
  11. import org.apache.hadoop.io.Writable;  
  12. import org.apache.hadoop.mapreduce.InputSplit;  
  13.   
  14.   
  15. public class FindMaxValueInputSplit extends InputSplit implements Writable{  
  16.   
  17.   
  18.     private int m_StartIndex;  
  19.     private int m_EndIndex;  
  20.     private ArrayWritable m_FloatArray=new ArrayWritable(FloatWritable.class);  
  21.       
  22.     public FindMaxValueInputSplit(){};  
  23.     /** 
  24.      * 这个自定义分类主要记录了Map函数的开始索引和结束索引,第一个map处理前50个小数,第二个map后50个小数 
  25.      * @param start 开始位置 
  26.      * @param end 结束位置 
  27.      */  
  28.     public FindMaxValueInputSplit(int start,int end){  
  29.         m_StartIndex=start;  
  30.         m_EndIndex=end;  
  31.         int len=m_EndIndex-m_StartIndex+1;  
  32.         int index=m_StartIndex;  
  33.           
  34.         FloatWritable[] result = new FloatWritable[len];  
  35.           
  36.         for (int i = 0; i < result.length; i++) {  
  37.             float f=FindMaxValueInputFormat.floatvalues[index];  
  38.             FloatWritable fW =new FloatWritable();  
  39.             fW.set(f);  
  40.             result[i]=fW;  
  41.             index++;  
  42.         }  
  43.         m_FloatArray.set(result);  
  44.     }  
  45.       
  46.     public void write(DataOutput out) throws IOException {  
  47.         out.writeInt(this.m_StartIndex);  
  48.         out.writeInt(this.m_EndIndex);  
  49.         this.m_FloatArray.write(out);  
  50.     }  
  51.   
  52.   
  53.     public void readFields(DataInput in) throws IOException {  
  54.         this.m_StartIndex=in.readInt();  
  55.         this.m_EndIndex=in.readInt();  
  56.         this.m_FloatArray.readFields(in);  
  57.     }  
  58.   
  59.   
  60.     @Override  
  61.     public long getLength() throws IOException, InterruptedException {  
  62.         return (this.m_EndIndex-this.m_StartIndex+1);  
  63.     }  
  64.   
  65.   
  66.     @Override  
  67.     public String[] getLocations() throws IOException, InterruptedException {  
  68.         return new String[]{"hadoop-2","hadoop-1"};  
  69.     }  
  70.       
  71.     public int getM_StartIndex(){   
  72.         return m_StartIndex;  
  73.     }  
  74.       
  75.     public int getM_EndIndex(){  
  76.         return m_EndIndex;  
  77.     }  
  78.       
  79.     public ArrayWritable getM_FloatArray(){   
  80.         return m_FloatArray;  
  81.     }  
  82.       
  83. }  




3、类 FindMaxValueRecordReader 继承 RecordReader :
  1. package inputformat;  
  2.   
  3.   
  4. import java.io.IOException;  
  5.   
  6.   
  7. import org.apache.hadoop.io.ArrayWritable;  
  8. import org.apache.hadoop.io.FloatWritable;  
  9. import org.apache.hadoop.io.IntWritable;  
  10. import org.apache.hadoop.mapreduce.InputSplit;  
  11. import org.apache.hadoop.mapreduce.RecordReader;  
  12. import org.apache.hadoop.mapreduce.TaskAttemptContext;  
  13. /** 
  14.  * 这个自定义 RecordReader 类,定义输入到map函数的输入格式 
  15.  * Key为偏移量 
  16.  * Value为float数组,长度为50 
  17.  * @author Administrator 
  18.  * 
  19.  */  
  20. public class FindMaxValueRecordReader extends RecordReader<IntWritable,ArrayWritable>{  
  21.     private int m_End;  
  22.     private int m_Index;  
  23.     private int m_Start;  
  24.     private IntWritable key=null;  
  25.     private ArrayWritable value=null;  
  26.     private FindMaxValueInputSplit fmvsplit=null;  
  27.       
  28.     @Override  
  29.     public void initialize(InputSplit split, TaskAttemptContext context)  
  30.             throws IOException, InterruptedException {  
  31.         fmvsplit=(FindMaxValueInputSplit)split;  
  32.         this.m_Start=fmvsplit.getM_StartIndex();  
  33.         this.m_End=fmvsplit.getM_EndIndex();  
  34.         this.m_Index=this.m_Start;  
  35.     }  
  36.     /** 
  37.      * 输出的key为  IntWritable 
  38.      * 输出的value为  ArrayWritable 
  39.      */  
  40.     @Override  
  41.     public boolean nextKeyValue() throws IOException, InterruptedException {  
  42.         if (key == null) {  
  43.             key=new IntWritable();  
  44.         }  
  45.         if (value == null) {  
  46.             value = new ArrayWritable(FloatWritable.class);  
  47.         }  
  48.         if (m_Index <= m_End) {  
  49.             key.set(m_Index);  
  50.             value=fmvsplit.getM_FloatArray();  
  51.             m_Index=m_End+1;  
  52.             return true;  
  53.         }else {  
  54.             return false;     
  55.         }  
  56.     }  
  57.   
  58.   
  59.     @Override  
  60.     public IntWritable getCurrentKey() throws IOException, InterruptedException {  
  61.         return key;  
  62.     }  
  63.   
  64.   
  65.     @Override  
  66.     public ArrayWritable getCurrentValue() throws IOException,  
  67.             InterruptedException {  
  68.         return value;  
  69.     }  
  70.   
  71.   
  72.     @Override  
  73.     public float getProgress() throws IOException, InterruptedException {  
  74.           
  75.         if (this.m_Index == this.m_End) {  
  76.             return 0.0f;  
  77.         }else {  
  78.             return Math.min(1.0f, (this.m_Index - this.m_Start)/(float)(this.m_End-this.m_Start));  
  79.         }  
  80.     }  
  81.   
  82.   
  83.     @Override  
  84.     public void close() throws IOException {  
  85.     }  
  86.       
  87. }  




4、mapper类 FindMaxValueMapper:
  1. package inputformat;  
  2.   
  3.   
  4. import java.io.IOException;  
  5.   
  6.   
  7. import org.apache.hadoop.io.ArrayWritable;  
  8. import org.apache.hadoop.io.FloatWritable;  
  9. import org.apache.hadoop.io.IntWritable;  
  10. import org.apache.hadoop.mapreduce.Mapper;  
  11. /** 
  12.  * Map函数的输入格式有所改变 
  13.  * @author Administrator 
  14.  * 
  15.  */  
  16. public class FindMaxValueMapper extends Mapper<IntWritable, ArrayWritable,IntWritable, FloatWritable>{  
  17.     private final static IntWritable one =new IntWritable(1);  
  18.     @Override  
  19.     protected void map(  
  20.             IntWritable key,  
  21.             ArrayWritable value,  
  22.             Mapper<IntWritable, ArrayWritable, IntWritable, FloatWritable>.Context context)  
  23.             throws IOException, InterruptedException {  
  24.           
  25.         FloatWritable[] floatArray =(FloatWritable[])value.toArray();  
  26.         float maxfloat=floatArray[0].get();  
  27.         float tmp;  
  28.         /** 
  29.          * 求一个InputSplit中的最大值 
  30.          */  
  31.         for (int i = 0; i < floatArray.length; i++) {  
  32.             tmp=floatArray[i].get();  
  33.             if (tmp>maxfloat) {  
  34.                 maxfloat=tmp;  
  35.             }  
  36.         }  
  37.         /** 
  38.          * 把一个map中的最大值输出出来 
  39.          */  
  40.         context.write(one, new FloatWritable(maxfloat));  
  41.     }  
  42.   
  43.   
  44. }  



5、Reducer 类 FindMaxValueReducer :
  1. package inputformat;  
  2.   
  3.   
  4. import java.io.IOException;  
  5. import java.util.Iterator;  
  6.   
  7.   
  8. import org.apache.hadoop.io.FloatWritable;  
  9. import org.apache.hadoop.io.IntWritable;  
  10. import org.apache.hadoop.io.Text;  
  11. import org.apache.hadoop.mapreduce.Reducer;  
  12. /** 
  13.  * Ruducer比较两个Map函数输出的最大值,结果输出在HDFS上面 
  14.  * 这个例子就比较两个值,有几个Map比较几个 
  15.  * @author Administrator 
  16.  * 
  17.  */  
  18. public class FindMaxValueReducer extends Reducer<IntWritable, FloatWritable, Text, FloatWritable>{  
  19.       
  20.     @SuppressWarnings("rawtypes")  
  21.     @Override  
  22.     protected void reduce(  
  23.             IntWritable k2,  
  24.             Iterable<FloatWritable> v2s,  
  25.             Reducer<IntWritable, FloatWritable, Text, FloatWritable>.Context context)  
  26.             throws IOException, InterruptedException {  
  27.           
  28.         Iterator it = v2s.iterator();  
  29.         float maxfloat=0,tmp;  
  30.         /** 
  31.          * 取第一个数 
  32.          */  
  33.         if (it.hasNext()) {  
  34.             maxfloat=((FloatWritable)(it.next())).get();  
  35.         }else {  
  36.             //集合为空时,输出迭代失败信息  
  37.             context.write(new Text("Max float value : "), null);  
  38.             return;  
  39.         }  
  40.         /** 
  41.          * 求最大值 
  42.          */  
  43.         while (it.hasNext()) {  
  44.             tmp=((FloatWritable)(it.next())).get();  
  45.             if (tmp > maxfloat) {  
  46.                 maxfloat = tmp;  
  47.             }  
  48.         }  
  49.         //把最大的那个值输出来  
  50.         context.write(new Text("Max float value : "), new FloatWritable(maxfloat));  
  51.     }  
  52.       
  53. }  




6、驱动类 MaxValueDriver :
  1. package inputformat;  
  2.   
  3.   
  4. import org.apache.hadoop.conf.Configuration;  
  5. import org.apache.hadoop.fs.Path;  
  6. import org.apache.hadoop.io.FloatWritable;  
  7. import org.apache.hadoop.io.IntWritable;  
  8. import org.apache.hadoop.mapreduce.Job;  
  9. import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;  
  10. import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat;  
  11.   
  12.   
  13. import com.sun.jersey.core.impl.provider.entity.XMLJAXBElementProvider.Text;  
  14. /** 
  15.  * 驱动类 
  16.  * @author Administrator 
  17.  * 
  18.  */  
  19. public class MaxValueDriver {  
  20.     public static void main(String[] args) throws Exception {  
  21.         Configuration conf = new Configuration();  
  22.         Job job=Job.getInstance(conf, MaxValueDriver.class.getSimpleName());  
  23.         job.setJarByClass(MaxValueDriver.class);  
  24.           
  25.         job.setNumReduceTasks(1);  
  26.           
  27.         job.setMapperClass(FindMaxValueMapper.class);  
  28.         job.setReducerClass(FindMaxValueReducer.class);  
  29.           
  30.         job.setMapOutputKeyClass(IntWritable.class);  
  31.         job.setMapOutputValueClass(FloatWritable.class);  
  32.           
  33.         job.setOutputKeyClass(Text.class);  
  34.         job.setOutputValueClass(FloatWritable.class);  
  35.           
  36.         job.setInputFormatClass(FindMaxValueInputFormat.class);  
  37.         job.setOutputFormatClass(TextOutputFormat.class);  
  38.           
  39.     //  FileInputFormat.setInputPaths(job, args[0]);  
  40.         FileOutputFormat.setOutputPath(job, new Path(args[0]));  
  41.           
  42.         job.waitForCompletion(true);  
  43.           
  44.     }  
  45. }  




第一次运行:
  1. [hadoop@hadoop ~]$ hdfs dfs -ls  /user/hadoop/output_inputformat1  
  2. Found 2 items  
  3. -rw-r--r--   3 hadoop supergroup          0 2015-09-04 15:09 /user/hadoop/output_inputformat1/_SUCCESS  
  4. -rw-r--r--   3 hadoop supergroup         29 2015-09-04 15:09 /user/hadoop/output_inputformat1/part-r-00000  
  5. [hadoop@hadoop ~]$ hdfs dfs -text  /user/hadoop/output_inputformat1/part-r-00000  
  6. Max float value :       0.9981093  
  7. [hadoop@hadoop ~]$  




第二次运行:
  1. [hadoop@hadoop ~]$ hdfs dfs -ls  /user/hadoop/output_inputformat2  
  2. Found 2 items  
  3. -rw-r--r--   3 hadoop supergroup          0 2015-09-05 11:43 /user/hadoop/output_inputformat2/_SUCCESS  
  4. -rw-r--r--   3 hadoop supergroup         29 2015-09-05 11:43 /user/hadoop/output_inputformat2/part-r-00000  
  5. [hadoop@hadoop ~]$  





查看两次运行内容:
  1. [hadoop@hadoop ~]$ hdfs dfs -text  /user/hadoop/output_inputformat1/part-r-00000  
  2. Max float value :       0.9981093  
  3. [hadoop@hadoop ~]$ hdfs dfs -text  /user/hadoop/output_inputformat2/part-r-00000  
  4. Max float value :       0.9966892  
  5. [hadoop@hadoop ~]$  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值