由于开始学习MapReduce编程已经有一段时间了,作为一个从编程中寻找自信和乐趣以及热爱编程的孩子来讲,手开始变得很“痒”了,很想小试一下身手。于是自己编写了TopK的代码。TopK的意思就是从原文件中找出词频排名前K的所有单词。首先分析该问题,从中我们可以得到启发:要想知道词频排名前K的所有单词,那么是不是要对所有的单词进行词频的统计啊?于是我们就联想到了一个比较经典的例子:WordCount的例子。是的,没错。就是它,统计原文件中每个单词的个数就靠它。

  但是,我们词频统计出来了,接下来需要做的就是如何找出词频排名前K的所有单词。如何找出词频排名前K呢?我们知道,WordCount得到的结果就是所有单词的词频情况,并且是已排好序的。所以,我们接下来需要做的是:

1、将所有相同词频的单词汇总,这一步就是map之后的shuffle过程可以得到相应的结果,只需要在map阶段将词频作为key,单词多作为value即可。

2、找出排名前k的词频的所有单词,并且按照词频的顺序排序,在这一步当中,很多人通过采用TreeMap的数据结构来实现,但是这里要注意点,TreeMap对于相同的键值是会进行覆盖的。因此无法操作相同键值的数据。也有些人对key进行封装,但同样还是避免不了有相同键值的结果。因此,我在这里采用的方法是将所有词频相同的单词用ArrayList存放起来,最后在将ArrayList的内容写入待hdfs中即可。

  综上所述,要实现TopK的结果,需要用到两个MR作业,一个是WordCount作业,一个是TopK的作业。

代码如下:

1、WordCount的部分:

  1. import java.io.IOException;
  2. import java.util.StringTokenizer;
  3.  
  4. import org.apache.hadoop.conf.Configuration;
  5. import org.apache.hadoop.fs.Path;
  6. import org.apache.hadoop.io.IntWritable;
  7. import org.apache.hadoop.io.LongWritable;
  8. import org.apache.hadoop.io.Text;
  9. import org.apache.hadoop.mapreduce.Job;
  10. import org.apache.hadoop.mapreduce.Mapper;
  11. import org.apache.hadoop.mapreduce.Reducer;
  12. import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
  13. import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
  14.  
  15. public class MyTopK {
  16.  
  17. public static class Mymap extends Mapper<LongWritable, Text, Text, IntWritable>{
  18.  
  19. private final IntWritable one =new IntWritable(1);
  20. private Text word =new Text();
  21.  
  22. public void map(LongWritable ikey,Text ivalue,Context context) throws IOException, InterruptedException{
  23. StringTokenizer str=new StringTokenizer(ivalue.toString());
  24. while(str.hasMoreTokens()){
  25. word.set(str.nextToken());
  26. context.write(word, one);
  27. }
  28. }
  29. }
  30.  
  31. public static class Myreduce extends Reducer<Text, IntWritable, Text, IntWritable>{
  32. private IntWritable result=new IntWritable();
  33.  
  34. public void reduce(Text ikey,Iterable<IntWritable> ivalue,
  35. Context context) throws IOException, InterruptedException{
  36. int sum=0;
  37. for(IntWritable val:ivalue){
  38. sum+=val.get();
  39. }
  40. result.set(sum);
  41. context.write(ikey, result);
  42. }
  43. }
  44.  
  45. //设置静态的函数,方便直接在main中通过类名 来调用
  46. public static boolean run(String in ,String out) throws IOException, ClassNotFoundException, InterruptedException{
  47.  
  48. Configuration conf =new Configuration();
  49.  
  50. Job job=new Job(conf,"Wordcount");
  51. job.setJarByClass(MyTopK.class);
  52. job.setMapperClass(Mymap.class);
  53. job.setReducerClass(Myreduce.class);
  54.  
  55. //设置map输出类型
  56. job.setMapOutputKeyClass(Text.class);
  57. job.setMapOutputValueClass(IntWritable.class);
  58.  
  59. //设置reduce的输出类型
  60. job.setOutputKeyClass(Text.class);
  61. job.setOutputValueClass(IntWritable.class);
  62.  
  63. //设置输入输出路径
  64. FileInputFormat.addInputPath(job, new Path(in));
  65. FileOutputFormat.setOutputPath(job, new Path(out));
  66.  
  67. return job.waitForCompletion(true);
  68. }
  69. }

  2、TopK的实现过程

  1. import java.io.IOException;
  2. import java.util.Map.Entry;
  3. import java.util.ArrayList;
  4. import java.util.Comparator;
  5. import java.util.Set;
  6. import java.util.StringTokenizer;
  7. import java.util.TreeMap;
  8. import java.util.regex.Pattern;
  9.  
  10. import org.apache.hadoop.conf.Configuration;
  11. import org.apache.hadoop.fs.Path;
  12. import org.apache.hadoop.io.IntWritable;
  13. import org.apache.hadoop.io.LongWritable;
  14. import org.apache.hadoop.io.Text;
  15. import org.apache.hadoop.mapreduce.Job;
  16. import org.apache.hadoop.mapreduce.Mapper;
  17. import org.apache.hadoop.mapreduce.Reducer;
  18. import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
  19. import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
  20. import org.apache.hadoop.mapreduce.lib.output.MultipleOutputs;
  21. import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat;
  22.  
  23. public class MyTopK1 {
  24.  
  25. public static class MyMap extends Mapper<LongWritable, Text, IntWritable, Text>{
  26.  
  27. IntWritable outkey=new IntWritable();
  28. Text outvalue=new Text();
  29.  
  30. public void map(LongWritable ikey,Text ivalue,Context context) throws IOException, InterruptedException{
  31. StringTokenizer str=new StringTokenizer(ivalue.toString());
  32. while(str.hasMoreTokens()){
  33. //这个表示是输入数据的每行数据,每一行包含了单词和单词的次数,这个内容否在ivalue中,下面需要将ivalue中的单词和单词的次数进行分离。
  34. String element=str.nextToken();
  35. if(Pattern.matches("\\d+", element)){//这里利用正则表达式来匹配单词的个数
  36. outkey.set(Integer.parseInt(element));//将单词的个数作为键值
  37. }else {
  38. outvalue.set(element);//将单词作为键值值
  39. }
  40. }
  41. context.write(outkey, outvalue);//在写的过程中会对单词的次数进行排序
  42. }
  43.  
  44. }
  45.  
  46. public static TreeMap<Integer, ArrayList<String> > hm =new TreeMap<Integer, ArrayList<String> >(new Comparator<Integer>() {
  47. public int compare(Integer v1,Integer v2){
  48. return v2.compareTo(v1);
  49. }
  50. });//用来选择出topK
  51. private static MultipleOutputs<Text, IntWritable> mos=null;//用来进行多文件输出
  52.  
  53. private static String path=null;
  54.  
  55. //通过shuffle过程之后,相同次数的单词就在一起了,并将这个数据作为reduce的输入数据
  56. public static class Myreduce extends Reducer<IntWritable, Text, Text, IntWritable>{
  57.  
  58. public void reduce(IntWritable ikey,Iterable<Text> ivalue,Context context) throws IOException,
  59. InterruptedException{
  60. ArrayList<String> tmp=new ArrayList<String>(10);
  61. for(Text val:ivalue){
  62. context.write(val,ikey);//输出全排序的内容
  63. // tmp.add(val.toString()); //这里会造成占用较多的内存,这里可以优化
  64.  
  65. //优化的方法就是限定列表的长度,由于是topk,所以每一个最多也就是10个即可
  66. if(tmp.size()<=10){
  67. tmp.add(val.toString());
  68. }
  69. }
  70. hm.put(ikey.get(), tmp);
  71. }
  72.  
  73. private static int topKNUM=10; //表示求最高的多少个数
  74. protected void cleanup(Context context) throws IOException,
  75. InterruptedException {
  76. //String path = context.getConfiguration().get("topKout");
  77. mos = new MultipleOutputs<Text, IntWritable>(context);
  78. Set<Entry<Integer, ArrayList<String> > > set = hm.entrySet();
  79.  
  80. for (Entry<Integer, ArrayList<String>> entry : set) {
  81. ArrayList<String> al = entry.getValue();
  82. if (topKNUM-al.size() > 0) {
  83. for (String word : al) {
  84. //if (topKNUM-- > 0) {
  85. mos.write("topKMOS", new Text(word), // 这里参数“topKMOS”表示一个属性名称
  86. new IntWritable(entry.getKey()), path);
  87. //}
  88. }
  89. }
  90. }
  91. mos.close();
  92. }
  93.  
  94. }
  95. @SuppressWarnings("deprecation")
  96. public static void run(String in,String out,String topkout) throws IOException, ClassNotFoundException, InterruptedException{
  97.  
  98. Configuration conf=new Configuration();
  99.  
  100. //创建作业,并制定map和reduce类
  101.  
  102. Job job=new Job(conf);
  103. job.setJarByClass(MyTopK1.class);
  104. job.setMapperClass(MyMap.class);
  105. job.setReducerClass(Myreduce.class);
  106.  
  107. //TopK的输出路径
  108. path=topkout;
  109. //conf.set("topKout",topkout);
  110.  
  111. //设置map输出的类型
  112. job.setMapOutputKeyClass(IntWritable.class);
  113. job.setMapOutputValueClass(Text.class);
  114.  
  115. //设置reduce的输出类型
  116. job.setOutputKeyClass(Text.class);
  117. job.setOutputValueClass(IntWritable.class);
  118.  
  119. //设置MultipleOutputs输出格式,//这里的第二个参数“topKMOS”要跟write方法中的参数相同
  120. MultipleOutputs.addNamedOutput(job, "topKMOS",TextOutputFormat.class, Text.class, IntWritable.class);
  121.  
  122. //设置输入输出格式
  123. FileInputFormat.addInputPath(job, new Path(in));
  124. FileOutputFormat.setOutputPath(job, new Path(out));
  125.  
  126. //提交作业
  127. job.waitForCompletion(true);
  128. }
  129. }

  3、程序的入口

  1. import java.io.IOException;
  2.  
  3. import org.apache.log4j.PropertyConfigurator;
  4.  
  5. public class TopKmain {
  6.  
  7. public static void main(String[] args) throws ClassNotFoundException, IOException, InterruptedException {
  8. // TODO Auto-generated method stub、、
  9. //这里要记住一点,手动加载一些log4j文件,一来可以去掉警告,二来可以在出现错误时,通过查看日志,了解错误详细内容
  10. String rootPath = System.getProperty("user.dir" );
  11. PropertyConfigurator.configure(rootPath+"\\log4j.properties");
  12.  
  13. //要统计字数,排序的文字
  14. String in = "hdfs://192.168.1.21:9000/input";
  15.  
  16. //统计字数后的结果
  17. String wordCoutoutput = "hdfs://192.168.1.21:9000/out";
  18.  
  19. //对统计完后的结果再排序后的内容
  20. String sort = "hdfs://192.168.1.21:9000/sort";
  21.  
  22. //指定前K条输出的文件名称
  23. String topK = "hdfs://192.168.1.21:9000/topK";
  24.  
  25. //如果统计字数的job完成后就开始排序
  26. if(MyTopK.run(in, wordCoutoutput)){
  27. MyTopK1.run(wordCoutoutput, sort,topK);
  28. }
  29. }
  30.  
  31. }

  

MapReduce实现TopK的示例的更多相关文章

  1. MapReduce框架结构及代码示例

    一个完整的 mapreduce 程序在分布式运行时有三类实例进程: 1.MRAppMaster:负责整个程序的过程调度及状态协调 2.MapTask:负责 map 阶段的整个数据处理流程 3.Redu ...

  2. MapReduce 编程模型 & WordCount 示例

    学习大数据接触到的第一个编程思想 MapReduce.   前言 之前在学习大数据的时候,很多东西很零散的做了一些笔记,但是都没有好好去整理它们,这篇文章也是对之前的笔记的整理,或者叫输出吧.一来是加 ...

  3. MongoDB的MapReduce用法及php示例代码

    MongoDB虽然不像我们常用的mysql,sqlserver,oracle等关系型数据库有group by函数那样方便分组,但是MongoDB要实现分组也有3个办法: * Mongodb三种分组方式 ...

  4. hadoop学习第三天-MapReduce介绍&&WordCount示例&&倒排索引示例

    一.MapReduce介绍 (最好以下面的两个示例来理解原理) 1. MapReduce的基本思想 Map-reduce的思想就是“分而治之” Map Mapper负责“分”,即把复杂的任务分解为若干 ...

  5. MapReduce原理与设计思想

    简单解释 MapReduce 算法 一个有趣的例子 你想数出一摞牌中有多少张黑桃.直观方式是一张一张检查并且数出有多少张是黑桃? MapReduce方法则是: 给在座的所有玩家中分配这摞牌 让每个玩家 ...

  6. 使用MapReduce实现一些经典的案例

    在工作中,很多时候都是用hive或pig来自动化执行mr统计,但是我们不能忘记原始的mr.本文记录了一些通过mr来完成的经典的案例,有倒排索引.数据去重等,需要掌握. 一.使用mapreduce实现倒 ...

  7. MapReduce极简教程

    一个有趣的例子 你想数出一摞牌中有多少张黑桃.直观方式是一张一张检查并且数出有多少张是黑桃?   MapReduce方法则是: 给在座的所有玩家中分配这摞牌 让每个玩家数自己手中的牌有几张是黑桃,然后 ...

  8. 大数据 --> MapReduce原理与设计思想

    MapReduce原理与设计思想 简单解释 MapReduce 算法 一个有趣的例子:你想数出一摞牌中有多少张黑桃.直观方式是一张一张检查并且数出有多少张是黑桃? MapReduce方法则是: 给在座 ...

  9. 指导手册04:运行MapReduce

    指导手册04:运行MapReduce   Part 1:运行单个MapReduce任务 情景描述: 本次任务要求对HDFS目录中的数据文件/user/root/email_log.txt进行计算处理, ...

随机推荐

  1. Oct22 实例测试

    实例: http://www.runoob.com/jsp/jsp-form-processing.html http://www.runoob.com/jsp/jsp-writing-filters ...

  2. Working with Data » Getting started with ASP.NET Core and Entity Framework Core using Visual Studio »迁移

    Migrations¶ 4 of 4 people found this helpful The Contoso University sample web application demonstra ...

  3. 【bzoj1027】合金

    [bzoj1027]合金 分析 数形结合+计算几何+Floyd最小环. http://blog.csdn.net/popoqqq/article/details/40539273 虽然这样占大家的很不 ...

  4. canvas实现钟表

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  5. IOS下移除按钮原生样式 -webkit-appearance

    IOS环境下的按钮都是经过美化的,但通常我们在设计web app的时候不需要这些看上去老土的样式,所以,去除这些显得很有必要. 下面这句代码就是重置这些样式的: -webkit-appearance: ...

  6. [redis] windwos下安装和使用redis

    一篇很好的入门学习文章:Redis学习 Redis是一种nosql数据库,在开发中常用做缓存. 1.下载地址: 低版本下载地址:https://github.com/dmajkic/redis/dow ...

  7. Qt之QSS(白色靓丽)

    简述 Qt助手中有关于各种部件的QSS详细讲解,资源很丰富,请参考:Qt Style Sheets Examples. 白色靓丽 - 一款漂亮的QSS风格. 你可以直接使用,也可以随意转载,但请务必保 ...

  8. sh脚本异常:bad interpreter: No such file or directory

    转:http://bluedest.iteye.com/blog/1674963 在Linux中执行.sh脚本,异常/bin/sh^M: bad interpreter: No such file o ...

  9. Longest Consecutive Sequence [LeetCode]

    Given an unsorted array of integers, find the length of the longest consecutive elements sequence. F ...

  10. struts2视频学习笔记 01-02

    网易云课堂-<struts2> 课时1 Struts2: WebWork2基础上发展而来,MVC框架,无侵入式设计. 提供了拦截器,类型转换器,支持多种表现层技术(JSP, freeMar ...