TopK的一个简单实现

转自:http://rangerwolf.iteye.com/blog/2119096

题外话:

《Hadoop in Action》 是一本非常不错的交Hadoop的入门书,而且建议看英文版。此书作者的英文表达非常简单易懂。相信有一定英文阅读能力的同学直接用英文版就能非常容易的上手~

 

 

进入正题。 这个题目是《Hadoop in Action》 上面的一道题目,求出Top K的值。

我自己随便弄了一个输入文件:

Java代码  收藏代码
  1. g   445  
  2. a   1117  
  3. b   222  
  4. c   333  
  5. d   444  
  6. e   123  
  7. f   345  
  8. h   456  

 

 

讲讲我的思路:

对于Top K的问题,首先要在每个block/分片之中找到这部分的Top K。并且由于只能输出一次,所以输出的工作需要在cleanup方法之中进行。为了简单,使用的是java之中的TreeMap,因为这个数据结构天生就带有排序功能。 而Reducer的工作流程跟Map其实是完全一致的,只是光Map一步还不够,所以只能再加一个Reduce步骤。

 

最终输出的格式为如下:(K=2)

Java代码  收藏代码
  1. 1117    a  
  2. 456    g  

所以需要使用map。 如果只需要输出大小的话,直接使用TreeSet会更高效一点。

 

下面是实现的代码:

Java代码  收藏代码
  1. package hadoop_in_action_exersice;  
  2.   
  3. import java.io.IOException;  
  4. import java.util.TreeMap;  
  5.   
  6. import org.apache.hadoop.conf.Configuration;  
  7. import org.apache.hadoop.fs.Path;  
  8. import org.apache.hadoop.io.IntWritable;  
  9. import org.apache.hadoop.io.LongWritable;  
  10. import org.apache.hadoop.io.Text;  
  11. import org.apache.hadoop.mapreduce.Job;  
  12. import org.apache.hadoop.mapreduce.Mapper;  
  13. import org.apache.hadoop.mapreduce.Reducer;  
  14. import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;  
  15. import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;  
  16.   
  17. public class TopK {  
  18.   
  19.     public static final int K = 2;  
  20.       
  21.     public static class KMap extends Mapper<LongWritable, Text, IntWritable, Text> {  
  22.           
  23.         TreeMap<Integer, String> map = new TreeMap<Integer, String>();   
  24.           
  25.         public void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {  
  26.               
  27.             String line = value.toString();  
  28.             if(line.trim().length() > 0 && line.indexOf("\t") != -1) {  
  29.                   
  30.                 String[] arr = line.split("\t", 2);  
  31.                 String name = arr[0];  
  32.                 Integer num = Integer.parseInt(arr[1]);  
  33.                 map.put(num, name);  
  34.                   
  35.                 if(map.size() > K) {  
  36.                     map.remove(map.firstKey());  
  37.                 }  
  38.             }  
  39.         }  
  40.   
  41.         @Override  
  42.         protected void cleanup(  
  43.                 Mapper<LongWritable, Text, IntWritable, Text>.Context context)  
  44.                 throws IOException, InterruptedException {  
  45.               
  46.             for(Integer num : map.keySet()) {  
  47.                 context.write(new IntWritable(num), new Text(map.get(num)));  
  48.             }  
  49.               
  50.         }  
  51.           
  52.     }  
  53.       
  54.       
  55.     public static class KReduce extends Reducer<IntWritable, Text, IntWritable, Text> {  
  56.           
  57.         TreeMap<Integer, String> map = new TreeMap<Integer, String>();  
  58.           
  59.         public void reduce(IntWritable key, Iterable<Text> values, Context context) throws IOException, InterruptedException {  
  60.                   
  61.             map.put(key.get(), values.iterator().next().toString());  
  62.             if(map.size() > K) {  
  63.                 map.remove(map.firstKey());  
  64.             }  
  65.         }  
  66.   
  67.         @Override  
  68.         protected void cleanup(  
  69.                 Reducer<IntWritable, Text, IntWritable, Text>.Context context)  
  70.                 throws IOException, InterruptedException {  
  71.             for(Integer num : map.keySet()) {  
  72.                 context.write(new IntWritable(num), new Text(map.get(num)));  
  73.             }  
  74.         }  
  75.     }  
  76.   
  77.     public static void main(String[] args) {  
  78.         // TODO Auto-generated method stub  
  79.           
  80.         Configuration conf = new Configuration();  
  81.         try {  
  82.             Job job = new Job(conf, "my own word count");  
  83.             job.setJarByClass(TopK.class);  
  84.             job.setMapperClass(KMap.class);  
  85.             job.setCombinerClass(KReduce.class);  
  86.             job.setReducerClass(KReduce.class);  
  87.             job.setOutputKeyClass(IntWritable.class);  
  88.             job.setOutputValueClass(Text.class);  
  89.             FileInputFormat.setInputPaths(job, new Path("/home/hadoop/DataSet/Hadoop/WordCount-Result"));  
  90.             FileOutputFormat.setOutputPath(job, new Path("/home/hadoop/DataSet/Hadoop/TopK-output1"));  
  91.             System.out.println(job.waitForCompletion(true));  
  92.         } catch (IOException e) {  
  93.             // TODO Auto-generated catch block  
  94.             e.printStackTrace();  
  95.         } catch (ClassNotFoundException e) {  
  96.             // TODO Auto-generated catch block  
  97.             e.printStackTrace();  
  98.         } catch (InterruptedException e) {  
  99.             // TODO Auto-generated catch block  
  100.             e.printStackTrace();  
  101.         }   
  102.     }  
  103. }  
posted @ 2015-11-25 22:55  五三中  阅读(423)  评论(0编辑  收藏  举报