大数据课程——MapReduce编程综合应用(2)
实验内容以及要求
现有一份汽车销售记录,销售记录包括时间、地点、邮政编码、车辆类型等信息,每条记录信息包含39项数据项。请利用MapReduce框架,编写程序实现如下功能:
(1)统计不同车型销售的年龄段分布情况,并分别按照车型和年龄段进行汇总(不考虑排序)。
注意:年龄段每10岁为1个年龄段(010、1120、21~30…)
输出格式参考如下:
车型1,年龄段1,300
车型1,年龄段1,300
…
车型1,年龄段2,300
…
车型2,年龄段1,300
…
车型1,小计,1800
…
小计,年龄段1,1800
…
(2)统计每月各品牌汽车的销量,每月销售量按照各品牌销量从高到低进行排序,并统计该月所有品牌汽车销售总量。
输出格式参考如下:
01,小计,3000
01,品牌1,500
01,品牌2,400
…
02,小计,1800
02,品牌1,400
02,品牌2,200
…
…
随便说两句
本次实验,由于题目有些特殊,需要设置一些KeyPair辅助类,用于作为输出、输入的Key值。
本次实验总体难度还是比较高的,主要是有了排序和统计需求,所以要着重写好KeyPair中的compareTo()方法和Redcuer中的cleanup()方法。
但这次实验中其实没怎么去使用自定义分区分组class,因为我个人感觉写不写对实验结果影响并不是很大。
另外实验过程中遇到的一个难点就是在实现“小计需求”的时候,需要想到一个方法去存储统计结果。最后经过自己的思考和与同学的讨论,最终想到了使用HashMap来解决这一需求。
1、统计不同车型销售的年龄段分布情况
实现思路
KeyPair中将车型和年龄段两个字段进行组合,分别设置为第一属性和第二属性。
- Map阶段,分割数据,从中提取出车型、年龄段数据,将<车型,年龄段>组合作为输出key,常量1作为输出value。
- Reducer阶段,统计ValueList中数据,并且使用两个HashMap分别对应车型的小计和年龄段的小计。将统计结果输出。另外在Reduce的cleanup阶段,将小计结果从HashMap中提取,并且输出。
CountCarKeyPair类,辅助类
import org.apache.hadoop.io.*;
import org.apache.hadoop.mapreduce.*;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
/**
* @author: 冰冷灬泡面
* @date: 2021/4/8 10:52
* @description:
* @modifiedBy:
*/
//自定义用于任务1的组合Key类
public class CountCarKeyPair implements WritableComparable<CountCarKeyPair> {
//组合Key属性
private String first;
private int second;
public int compareTo(CountCarKeyPair o) {
int res = this.first.compareTo(o.first);
if (res != 0) {
return res;
}
else {
return Integer.valueOf(this.second).compareTo(Integer.valueOf(o.getSecond()));
}
}
public void write(DataOutput dataOutput) throws IOException {
dataOutput.writeUTF(first);
dataOutput.writeInt(second);
}
public void readFields(DataInput dataInput) throws IOException {
this.first = dataInput.readUTF();
this.second = dataInput.readInt();
}
public String getFirst() {
return first;
}
public void setFirst(String first) {
this.first = first;
}
public int getSecond() {
return second;
}
public void setSecond(int second) {
this.second = second;
}
}
Map代码
import org.apache.hadoop.mapreduce.*;
import org.apache.hadoop.io.*;
import java.io.IOException;
/*
* @author: 冰冷灬泡面
* @date: 2021/4/8 10:51
* @description:
* @modifiedBy:
*/
public class CountCarMapper extends Mapper<LongWritable, Text, CountCarKeyPair, IntWritable> {
private static final IntWritable one = new IntWritable(1);
@Override
protected void map(LongWritable key, Text value, Mapper<LongWritable, Text, CountCarKeyPair, IntWritable>.Context context) throws IOException, InterruptedException {
String data = value.toString();
//csv格式的文件以逗号分隔数据
String[] datas = data.split(",");
//数据清洗,无用数据直接剔除
//其中第38项为年龄,第9项为车型
if(datas.length != 39 || datas[37]