1、案例分析
TopN分析法指从研究对象中按照某一指标进行倒序或者正序排列,取其中所需要的N个数据,并对这N个数据进行重点分析的方法。
在自己的目录下创建数据文件num.txt
使用MapReduce技术提取上述文本中最大五个数据,并将最终结果汇总到指定文件中。
2、案例实现
(1)Map阶段实现
使用idea开发工具前打开以前创建的Maven项目,并且新创建cn.itcast.mr.topN包,在该路径下编写自定义Mapper类TopNMapper,如下图所示
public class TopNMapper extends Mapper<LongWritable, Text, NullWritable, IntWritable> {
private TreeMap<Integer,String>repToRecordMap=new TreeMap<Integer,String>();
@Override
public void map(LongWritable key,Text vaule,Context context){
String line=vaule.toString();
String[] nums=line.split(" ");
for (String num:nums){
//读取每行数据写入TreeMap,超过五个移除最小数值
repToRecordMap.put(Integer.parseInt(num)," ");
if (repToRecordMap.size()>5){
repToRecordMap.remove(repToRecordMap.firstKey());
}
}
}
//重写cleanup()方法,读取完所有文件行数据后,再输出到reduce阶段
@Override
protected void cleanup(Context context){
for (Integer i:repToRecordMap.keySet()){
try{
context.write(NullWritable.get(),new IntWritable(i));
}catch (Exception e){
e.printStackTrace();
}
}
}
}
该代码作用是先将文件中每行数据进行切割提取,并把数据保存在TreeMap中,判断TreeMap是否大于5,如果大于5就需要移除最小的数据。由于数据是逐行读取,如果这时就向外写数据,那么TreeMap就保存了每一行最大的五个数,因此需要在clean()方法里编写context.write()方法,这样保证了当前MapTask中TreeMap保存了当前文件最大的五条数据后,在输出到reduce阶段。
(2)Reduce阶段实现
根据Map阶段的输出结果形式,同样在cn.itcast.mr.topN包下,自定义Reducer类,TopNReducer,如下图
public class TopNReducer extends Reducer<NullWritable,IntWritable,NullWritable,IntWritable> {
//创建TreeMap,并实现自定义倒序排序规则
private TreeMap<Integer,String>repToRecordMap=new TreeMap<Integer,String>(new Comparator<Integer>() {
@Override
//返回复数表示:a<b
//返回0表示:a=b
//返回正数表示:a>b
public int compare(Integer a, Integer b) {
return b-a;
}
});
public void reduce(NullWritable key,Iterable<IntWritable>vaules,Context context)throws IOException,InterruptedException{
for (IntWritable value:vaules){
repToRecordMap.put(value.get(),"");
if (repToRecordMap.size()>5){
repToRecordMap.remove(repToRecordMap.lastKey());
}
}
for (Integer i:repToRecordMap.keySet()){
context.write(NullWritable.get(),new IntWritable(i));
}
}
}
上图中的代码,首先编写TreeMap自定义排序规则, 当需求最大值时,只需要在compare()方法中返回正数即可满足倒序排列,在数据量比较大的情况下,reduce()方法依然是要满足时刻判断TreeMap中存放数据是前5个数,并最终遍历输出最大的5个数。
(3)Driver程序主类实现
编写MapReduce程序运行主类TopNDriver,如下图
public class TopNDriver {
public static void main(String[] args)throws Exception{
Configuration configuration=new Configuration();
Job job=Job.getInstance(configuration);
job.setJarByClass(TopNDriver.class);
job.setMapperClass(TopNMapper.class);
job.setReducerClass(TopNReducer.class);
job.setNumReduceTasks(1);
//map阶段输出的key
job.setMapOutputKeyClass(NullWritable.class);
//map阶段输出的value
job.setMapOutputValueClass(IntWritable.class);
//reduce阶段输出的key
job.setOutputKeyClass(NullWritable.class);
//reduce阶段输出的value
job.setOutputValueClass(IntWritable.class);
FileInputFormat.setInputPaths(job,new Path("D:\\test\\TopN"));
FileOutputFormat.setOutputPath(job,new Path("D:\\test\\output29"));
boolean res=job.waitForCompletion(true);
System.exit(res?0:1);
}
}
本案例的演示采用本地运行模式,对指定的本地 D:\\test\\input目录下的源文件(开头的文本截图,需要提前准备),实现TopN分析,得到文件中最大的五个数,并将结果输出到本地D:\\test\\output目录下(output目录不需要提前创建,否则会报错),设置完毕后,运行程序。
(4)效果测试
为保证MapReduce文件能运行,首先在本地D:\\test\\input目录下创建num.txt文件,接着执行MapReduce程序的程序入口TopDriver类,正常执行后,会在D:\\test\\output目录下生成如下文件
使用记事本打开part-r-00000文件生成如下结果
从上图中可以看出,通过Hadoop的 MapReduce程序提取出文件的Top5个数据内容。