头歌-第1关:MapReduce的编程开发-排序

本文介绍了如何使用MapReduce编程技术,根据用户行为CSV数据文件中的商品点击浏览行为,统计商品点击量并进行排序。重点讲解了排序过程,包括溢写阶段、归并排序,以及cleanup()方法的作用。
摘要由CSDN通过智能技术生成

任务描述

本关任务:根据用户行为数据,编写 MapReduce 程序来统计出商品点击量排行。

相关知识
排序概述
  1. 在 MapReduce 的 Shuffle 的过程中执行了三次排序,分别是: map 中的溢写阶段:根据分区以及 key 进行快速排序。 map 中合并溢写文件:将同一分区的多个溢写文件进行归并排序,合成一个大的溢写文件。 reduce 输入阶段:将同一分区,来自不同 map task 的数据文件进行归并排序。

  2. 在 MapReduce 整个过程中,默认是会对输出的键值对按照 key 进行排序的,而且是使用快速排序。map 输出的排序的,其实也就是上面的溢写过程中的排序。reduce 输出的排序,即 reduce 处理完数据后,MapReduce内部会自动对输出的键值对按照key进行排序。

数据文件格式说明

这是编程中用到的电商数据,为 CSV 格式,文件名user_behavior.csv,大小9948行,前几行示例如下:

 
  1. 1002309,1008608,手机,pv
  2. 1002573,1009007,耳机,pv
  3. 1001541,1008614,手机,pv
  4. 1001192,1008612,手机,pv
  5. 1001016,1008909,平板电脑,buy
  6. 1001210,1008605,手机,pv
  7. 1001826,1008704,笔记本,pv
  8. 1002208,1008906,平板电脑,pv
  9. 1002308,1008702,笔记本,pv
  10. 1002080,1008702,笔记本,cart
  11. 1001525,1008702,笔记本,cart
  12. 1002749,1008702,笔记本,pv
  13. 1002134,1008704,笔记本,cart
  14. 1002497,1008608,手机,pv
  15. ···
  16. ---总共 9948行---
  • 每一行数据(4列)分别表示: 用户id, 商品id, 商品类别, 用户行为
  • 商品类别有 手机、平板电脑、笔记本、智能手表、耳机,总共5大类别;
  • 用户行为pv代表点击浏览cart代表加入购物车fav代表添加到喜欢buy代表购买
商品点击量排行

即统计出每个商品id中用户行为是pv(点击浏览)的数量,reduce的输出最后是按点击量的大小从大到小排序。

cleanup()方法

编程中可能会用到 cleanup() 方法,cleanup 方法是 mapper/reduce 对象执行完所有的 map/reduce 方法之后最后执行的方法,可用于清理资源释放或清理工作;默认继承的父类方法为空,什么也不做。

编程要求

根据提示,在右侧编辑器补充代码,计算得出商品点击量排行。

  • main 方法已给出,其中 Job 和输入输出路径已配置完成,无需更改;
  • map 和 reduce 的输入输出 key、value 已给出;
  • 编程中直接写 map 与 reduce 过程的主要内容即可。

预期输出格式(按点击量从大到小):

 
  1. 商品id,点击量
  2. 商品id,点击量
  3. ···
  4. ···
测试说明

平台会对你编写的代码进行测试,如果编写的 MapReduce 输出与预期一致,则通过。

注:出于显示原因,网页端的 mapreduce 的输出结果中制表符统一用逗号代替显示,但在实际 reduce 结果中 key\value 仍是原样制表符分割,这只是显示上的变化,不影响编程与评测结果


开始你的任务吧,祝你成功!

代码如下:

package educoder;

import java.io.IOException;

import java.util.LinkedList;

import java.util.List;

import java.util.stream.Collectors;

import org.apache.hadoop.conf.Configuration;

import org.apache.hadoop.fs.Path;

import org.apache.hadoop.io.IntWritable;

import org.apache.hadoop.io.Text;

import org.apache.hadoop.mapreduce.Job;

import org.apache.hadoop.mapreduce.Mapper;

import org.apache.hadoop.mapreduce.Reducer;

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

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

/**

 * UserLoseDriver

 */

public class ItemClickRankDriver {

    public static class ThisMap extends Mapper<Object, Text, Text, IntWritable> {

        private static IntWritable one = new IntWritable(1);

        @Override

        protected void map(Object key, Text value, Context context) throws IOException, InterruptedException {

           

            /*** 在这编写map内容 ****/

            /********** Begin **********/

//1. 分割每行数据

            String[] atts=value.toString().split(",");

           

            //2. 得到商品id

            String item=atts[1];

            //3. 得到行为属性

            String behavior=atts[3];

            //4. 如果行为属性是 'pv',则写入到map输出

            if(behavior.equals("pv")){

                context.write(new Text(item),one);

            }

            /********** End **********/

        }

    }

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

        //对象实例,用来保存reduce方法中处理的数据

        List<Object[]> list=new LinkedList<>();

        @Override

        protected void reduce(Text key, Iterable<IntWritable> values, Context context)

                throws IOException, InterruptedException {

            /*** 在这编写reduce内容 ****/

            /********** Begin **********/

            int sum=0;

            for(IntWritable one:values){

                sum+=one.get();

            }

            list.add(new Object[] {key.toString(),Integer.valueOf(sum)});

            // 统计同key总数, 把key和sum写入到list中

            /********** End **********/

        }

       

        //cleanup方法,即reduce对象执行完所有的reduce方法后最后执行的方法

        @Override

        protected void cleanup(Reducer<Text, IntWritable, Text, IntWritable>.Context context)

                throws IOException, InterruptedException {

    list=list.stream().sorted((o1,o2) -> {return ((int)o1[1] - (int)o2[1]);}).collect(Collectors.toList());      

        for(int i=list.size()-1;i>=0;i--){

            Object[] o=list.get(i);

            context.write(new Text((String) o[0]),new IntWritable((int) o[1]));

        }    

            /********** Begin **********/

           

            /********** End **********/

        }

    }

    public static void main(String[] args) throws Exception {

        Configuration conf = new Configuration();

        Job job = Job.getInstance(conf, "商品点击量排行");

        job.setJarByClass(ItemClickRankDriver.class);

        job.setMapperClass(ThisMap.class);

        job.setMapOutputKeyClass(Text.class);

        job.setMapOutputValueClass(IntWritable.class);

        job.setReducerClass(ThisReduce.class);

        job.setOutputKeyClass(Text.class);

        job.setOutputValueClass(IntWritable.class);

        FileInputFormat.addInputPath(job, new Path(args[0]));

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

        System.exit(job.waitForCompletion(true) ? 0 : 1);

    }

}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值