案例:分组求top1、求topN

====
案例:分组求top1

自定义GroupingComparator求取topN
GroupingComparator是mapreduce当中reduce端的一个功能组件,主要的作用是决定哪些数据作为一组,调用一次reduce的逻辑,默认是每个不同的key,作为多个不同的组,每个组调用一次reduce逻辑,我们可以自定义GroupingComparator实现不同的key作为同一个组,调用一次reduce逻辑
3.1 需求
有如下订单数据
订单id    商品id    成交金额
Order_0000001    Pdt_01    222.8
Order_0000001    Pdt_05    25.8
Order_0000002    Pdt_03    522.8
Order_0000002    Pdt_04    122.4
Order_0000002    Pdt_05    722.4
Order_0000003    Pdt_01    222.8

现在需要求出每一个订单中成交金额最大的一笔交易

3.2 分析
1、利用“订单id和成交金额”作为key,可以将map阶段读取到的所有订单数据按照id分区,按照金额排序,发送到reduce
2、在reduce端利用groupingcomparator将订单id相同的kv聚合成组,然后取第一个即是最大值


第一步:读取文件,解析成key, value对。
第二步:自定义map逻辑,接收k1,v1,转换成新的k2,v2。
k1: LongWritable; v1: Text
k2: OrderBean(orderId, price); v2: NullWritable
第一点:一定要保证:相同orderID的数据到同一个reduce里面去,以订单id作为key2。
第二点:我们相同的订单id的数据,需要按照金额进行排序。需要按照谁排序,就把谁作为k2。金额作为key2。
所以,定义一个orderBean,有两个属性,一个是orderId订单号,一个是price金额。以OrderBean作为key2。
默认分区规则HashPartitioner
自定义分区规则,以订单id作为分区一句,相同的订单id发送到同一个reduce里面去。
排序以OrderBean里面的金额进行排序。注意,排序有要求,只有相同的orderId里面的金额才需要排序。

第三步:自定义分区,以我们的OrderBean里面的orderId作为分区的依据。
第四步:排序。按照相同订单的金额进行排序,不同订单金额没有可比性。
第五步:规约。
第六步:分组。接收k2,v2。
k2: OrderBean(orderId, price); v2: NullWritable
每一条数据,都是一个独立的组,每一条数据分完组后,都要去独立地调用一次reduce逻辑。
需要自定义分组,我们的任务相同订单id的数据是同一个组里面的数据,给我们合并为一组。
相同的订单id作为一组,我们这个组里面有多条数据,但是只给我们显示了金额最大的那一条。(分组求top1)

第七步:自定义reduce逻辑接收k2,v2,直接输出k2,就是我们的最大值top1。
第八步:输出文件。


代码实现
第一步:定义OrderBean
package cn.itcast.demo5.top1;

import org.apache.hadoop.io.WritableComparable;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;

public class OrderBean implements WritableComparable<OrderBean> {

    private String orderId;
    private Double price;


    /**
     * 比较器
     * @param o
     * @return
     */
    @Override
    public int compareTo(OrderBean o) {
        //第一个问题:不同订号,不用比较价格排序
        int i = this.orderId.compareTo(o.orderId);
        if(i ==0){
            //订单号相等了
            //继续比较交个
           i = this.price.compareTo(o.price);
           i = -i;
        }
        return i;
    }

    /**
     * 序列化的方法
     * @param out
     * @throws IOException
     */
    @Override
    public void write(DataOutput out) throws IOException {
        out.writeUTF(orderId);
        out.writeDouble(price);

    }

    /**
     * 反序列化的方法
     * @param in
     * @throws IOException
     */
    @Override
    public void readFields(DataInput in) throws IOException {
        this.orderId = in.readUTF();
        this.price = in.readDouble();

    }

    public String getOrderId() {

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值