map/reduce实例(四)

map/reduce经典案例——wordcount进阶

输入数据

hello world
dog fish
hadoop 
spark
hello world
dog fish
hadoop 
spark
hello world
dog fish
hadoop 
spark

要求 , 输出出现次数前三的单词,用一次map/reduce完成。

要点分析:我们知道mapreduce有分许聚合的功能,所以第一步就是:把每个单词读出来,然后在reduce中聚合,求出每个单词出现的次数但是怎么控制只输出前三名呢?我们知道,map是读一行执行一次,reduce是每一组执行一次所以只用map,和reduce是无法控制输出的次数的但是我们又知道,无论map或者reduce都有 setUp 和cleanUp而且这两个执行一次所以我们可以在reduce阶段把每一个单词当做key,单词出现的次数当做value,每一组存放到一个map里面,此时只存,不写出。在reduce的cleanUp阶,map排序,然后输出前三名。

代码分析:在reduce阶段并不直接context输出而是将reduce的结果输出到一个hashmap中,然后在cleanup中将map转为list而后对list进行排序。

map阶段

 public static class wordcmapper extends Mapper<LongWritable , Text , Text , IntWritable>{
        @Override
        protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
            String[] words = value.toString().split(" ");
            for (String word: words) {
                context.write(new Text(word),new IntWritable(1));
            }
        }
    }

map阶段和之前相同。

reduce阶段

public static class wordcreducer extends Reducer<Text ,IntWritable , Text , IntWritable>{

    HashMap map = new HashMap<String , Integer>();
    @Override
    protected void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {
        int count = 0;
        for (IntWritable v:values) {
            count +=v.get();
        }
        map.put(key.toString() , count);
    }

    @Override
    protected void cleanup(Reducer<Text , IntWritable , Text , IntWritable>.Context context) throws IOException, InterruptedException {
        LinkedList<Map.Entry<String, Integer>> linkedList = new LinkedList<Map.Entry<String, Integer>>(map.entrySet());
        Collections.sort(linkedList, new Comparator<Map.Entry<String, Integer>>() {
            public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {
                return o2.getValue() - o1.getValue();
            }
        });
        int size = linkedList.size();
        for (int i = 0 ; i <size ; i++) {
            context.write(new Text(linkedList.get(i).getKey()) , new IntWritable(linkedList.get(i).getValue()));
        }
    }
}

在reducer类中reduce方法外面重写cleanup方法。在cleanup方法中将map转为list对list进行排序。

public static void main(String[] args) throws Exception {
        Configuration conf = new Configuration();
        Job job = new Job();
    	job.setJarByClass(wordcmapred.class);
    	job.setMapperClass(wordcmapper.class);
    job.setReducerClass(wordcreducer.class);

    job.setMapOutputKeyClass(Text.class);
    job.setMapOutputValueClass(IntWritable.class);

    job.setOutputKeyClass(Text.class);
    job.setOutputValueClass(IntWritable.class);

    FileInputFormat.setInputPaths(job,new Path(args[0]));
    FileOutputFormat.setOutputPath(job,new Path(args[1]));

    if(!job.waitForCompletion(true)){
        return;
    }
}

job类

总结:在mapper和reducer中都有setup方法和cleanup方法,这两个方法在map/reduce中只执行一次,可以用于加载资源或者清除资源,也可以用来做一些轻量级工作,如果执行一些比较大的工作量还是不要在这里面执行,严重影响分布式的优势。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值