继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

MapReduce倒排索引

至尊宝的传说
关注TA
已关注
手记 129
粉丝 82
获赞 463

倒排索引就是某个单词在那些文件中出现了多少次,而在最开始学习的Wordcount中是某个文件中那些单词出现了多少次,两者正好相反,就像在搜索引擎上搜索一个单词,下面就会罗列出这个单词在哪些文件里出现过。

    首先我们就要想好,什么是key,什么是value,map输出的结果是什么,reduce怎样处理才能够得到想要的结果。

    在倒排索引中,我们需要得到单词-文件名-次数,因为这个次数是这个单词在这个文件中出现的次数,所以此时单词和文件应该合在一起作为key,次数作为value。 但一次reduce过后还需要将结果中单词合并。因为我们最后要的结果是单词-文件名~次数,文件名~次数······所以需要两次reduce,就用到了combiner 。

    此时就变得清晰了,第一次map要输出单词和文件名共同为键,用combiner计算出次数,combiner再输出单词和文件名-次数,用reduce进行合并。combine就相当于一次reducer,但combiner在map端。

  1. package mr.inverseIndex;  

  2.   

  3. import org.apache.hadoop.conf.Configuration;  

  4. import org.apache.hadoop.fs.FileSystem;  

  5. import org.apache.hadoop.fs.Path;  

  6. import org.apache.hadoop.io.LongWritable;  

  7. import org.apache.hadoop.io.Text;  

  8. import org.apache.hadoop.mapreduce.Job;  

  9. import org.apache.hadoop.mapreduce.Mapper;  

  10. import org.apache.hadoop.mapreduce.Reducer;  

  11. import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;  

  12. import org.apache.hadoop.mapreduce.lib.input.FileSplit;  

  13. import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;  

  14.   

  15. import java.io.IOException;  

  16. import java.net.URI;  

  17. import java.net.URISyntaxException;  

  18.   

  19. public class ForInverseMR {  

  20.     public static class ForMapper extends Mapper<LongWritable,Text,Text,Text>{  

  21.         private Text oKey=new Text();  

  22.         private Text oValue=new Text();  

  23.         @Override  

  24.         protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {  

  25.             String filename=((FileSplit)context.getInputSplit()).getPath().getName();//获得文件名  

  26.             String strs[]=value.toString().split(" ");  

  27.             for(String s:strs){   //遍历单词  

  28.                 oKey.set(s+"-"+filename);//将单词和文件名设置为键      

  29.                 context.write(oKey,oValue);//value为空,为了计数  

  30.             }  

  31.             //输出键值对格式 单词-文件名  

  32.         }  

  33.     }  

  34.   

  35.     public static class ForCombiner extends Reducer<Text,Text,Text,Text>{  

  36.         private Text oKey=new Text();  

  37.         private Text oValue=new Text();  

  38.         @Override  

  39.         protected void reduce(Text key, Iterable<Text> values, Context context) throws IOException, InterruptedException {  

  40.             int count=0;//次数  

  41.             for (Text text:values){  

  42.                 count++;  

  43.             }  

  44.             String strs[]=key.toString().split("-");//将键重新拆分为单词  

  45.             oKey.set(strs[0]);  

  46.             oValue.set(strs[1]+"~"+count);  

  47.             context.write(oKey,oValue);  

  48.             //输出键值对格式 单词1 文件名1~次数  

  49.             //              单词1 文件名2~次数  

  50.         }  

  51.     }  

  52.   

  53.     public static class ForReducer extends Reducer<Text,Text,Text,Text>{  

  54.         private Text oValue=new Text();  

  55.         @Override  

  56.         protected void reduce(Text key, Iterable<Text> values, Context context) throws IOException, InterruptedException {  

  57.             StringBuilder sb=new StringBuilder();  

  58.             for(Text text:values){  

  59.                 sb.append(text.toString()).append(",");  

  60.             }  

  61.             sb.delete(sb.length()-1,sb.length());//去掉最后一个逗号  

  62.             oValue.set(sb.toString());  

  63.             context.write(key,oValue);  

  64.             //输出格式 单词 文件1~次数,文件2~次数···  

  65.         }  

  66.     }  

  67.   

  68.     public static void main(String[] args) throws IOException, URISyntaxException, ClassNotFoundException, InterruptedException {  

  69.         Job job= Job.getInstance();  

  70.         // 设置map的类  

  71.         job.setMapperClass(ForInverseMR.ForMapper.class);  

  72.         //设置combiner的类  

  73.         job.setCombinerClass(ForInverseMR.ForCombiner.class);  

  74.         //设置reduce的类  

  75.         job.setReducerClass(ForInverseMR.ForReducer.class);  

  76.   

  77.         //设置map的输出key value 类型  

  78.         job.setMapOutputKeyClass(Text.class);  

  79.         job.setMapOutputValueClass(Text.class);  

  80.         // 设置reduce 输出的key value 类型  

  81.         job.setOutputKeyClass(Text.class);  

  82.         job.setOutputValueClass(Text.class);  

  83.   

  84.         //设置输入文件的路径  

  85.         FileInputFormat.addInputPath(job,new Path("F:\\forTestData\\inverseIndex\\data"));  

  86.         //设置输出文件的路径//如果重复文件夹就删  

  87.         FileSystem fs=FileSystem.get(new URI("file://F://out"),new Configuration());  

  88.         if(fs.exists(new Path("F://out"))){  

  89.             fs.delete(new Path("F://out"),true);  

  90.         }  

  91.         FileOutputFormat.setOutputPath(job,new Path("F://out"));  

  92.   

  93.         //保证reduce的个数是1  

  94.         job.setNumReduceTasks(1);  

  95.         //true表示将运行进度等信息及时输出给用户,false的话只是等待作业结束  

  96.         job.waitForCompletion(true);  

  97.     }  

  98. }  

    完成。

原文出处


打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP