1.背景
reduce处理的数据,是根据key值进行分组,有时候,需要根据对象的某个字段进行分组,他们同时进入reduce端进行处理
2.自定义分组步骤
- 自定义类继承WritableComparator
- 重写compare()方法
- 创建一个构造将比较对象的类传给父类
protected OrderGroupingComparator() {
super(OrderBean.class, true);
}
原因分析
源码:
protected WritableComparator(Class<? extends WritableComparable> keyClass, Configuration conf, boolean createInstances) {
this.keyClass = keyClass;
this.conf = conf != null ? conf : new Configuration();
if (createInstances) {
this.key1 = this.newKey();
this.key2 = this.newKey();
this.buffer = new DataInputBuffer();
} else {
this.key1 = this.key2 = null;
this.buffer = null;
}
}
1.根据对象的某一字段进行分组,前提是对象必须存在,即必须实例化
2.由源码可知,当调用无参构造方法时,会判断createInstances是否为true,如果不是,则赋值为Null,否则会实例化对象
3.需求
有如下订单数据
表4-2 订单数据
订单id | 商品id | 成交金额 |
---|---|---|
0000001 | Pdt_01 | 222.8 |
Pdt_02 | 33.8 | |
0000002 | Pdt_03 | 522.8 |
Pdt_04 | 122.4 | |
Pdt_05 | 722.4 | |
0000003 | Pdt_06 | 232.8 |
Pdt_02 | 33.8 |
现在需要求出每一个订单中最贵的商品。
(1)输入数据
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-W8lKCMs5-1605341517472)(file:///C:\Users\14812\AppData\Local\Temp\ksohtml4628\wps5.png)]
(2)期望输出数据
1 222.8
2 722.4
3 232.8
4.需求分析
(1)利用“订单id和成交金额”作为key,可以将Map阶段读取到的所有订单数据按照id升序排序,如果id相同再按照金额降序排序,发送到Reduce。
(2)在Reduce端利用groupingComparator将订单id相同的kv聚合成组,然后取第一个即是该订单中最贵商品
5.代码实现
1.bean对象
package com.zj.practice.mapreduce07.order_group_sort;
import org.apache.hadoop.io.WritableComparable;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
/**
* 需求: --> 辅助排序(分组排序)
* (1)利用“订单id和成交金额”作为key,可以将Map阶段读取到的所有订单数据按照id升序排序,
* 如果id相同再按照金额降序排序,发送到Reduce。
* (2)在Reduce端利用groupingComparator将订单id相同的kv聚合成组,
* 然后取第一个即是该订单中最贵商品
*/
public class orderBean implements WritableComparable<orderBean> {
/**
* 订单id
*/
private int