mapreduce求topN
(1)利用TreeMap排序,该方式利用小顶堆和集合重复原理的方式 , 每过来一个数据 , 跟堆顶数据进行比较 , 如果比最小的大 , 则将过来的数据替换堆顶元素 , 否则直接跳过数据 . 以此对数据进行排序。
(2)在众多的Mapper的端,首先计算出各端Mapper的TopN,然后在将每一个Mapper端的TopN汇总到Reducer端进行计算最终的TopN,这样就可以最大化的提高运行并行处理的能力,通时极大的减少网络的Shuffle传输数据,从而极大的加快的整个处理的效率
(3)setup()与cleanup()方法
1、setup(),此方法被MapReduce框架仅且执行一次,在执行Map任务前,进行相关变量或者资源的集中初始化工作。若是将资源初始化工作放在方法map()中,导致Mapper任务在解析每一行输入时都会进行资源初始化工作,导致重复,程序运行效率不高!
2、cleanup(),此方法被MapReduce框架仅且执行一次,在执行完毕Map任务后,进行相关变量或资源的释放工作。若是将释放资源工作放入方法map()中,也会导致Mapper任务在解析、处理每一行文本后释放资源,而且在下一行文本解析前还要重复初始化,导致反复重复,程序运行效率不高!
注意:若map与reduce都出现setup()与cleanup()方法,MR都只会执行一次setup()与cleanup()方法。
import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.Path; import org.apache.hadoop.io.IntWritable; import org.apache.hadoop.io.LongWritable; 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; import org.apache.hadoop.util.GenericOptionsParser; import java.io.IOException; import java.util.Map; import java.util.Set; import java.util.TreeMap; import java.util.TreeSet; //题目:在大量的数据中计算出资费最高的N个订单,数据格式为8,1818,9000,20,按“,“进行切分分别对应订单ID 用户ID 资费 业务ID。 public class SortedTopN { public static class SortedTopNMapper extends Mapper<LongWritable, Text, Text, Text> { @Override protected static void setup(Context context) throws IOException, InterruptedException { int N = context.getConfiguration().getInt("topn", 5); //获取输入的TopN的长度 TreeMap<Integer,String> set = new TreeMap<>(); } @Override protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException { //数据格式为8,1818,9000,20,按“,“进行切分 String[] data = value.toString().split(","); if (4 == data.length) { //符合格式的数据才进行处理 int cost = Integer.valueOf(data[2]); //获取订单的消费金额 map.put(cost,""); if (map.size() > N) { map.remove(map.firstKey()); } } for (int i : map.keySet()) { context.write(NullWritable.get(),new IntWritable(i)); } } } //reduce public static class SortedTopNReducer extends Reducer<Text, Text, Text, Text> { @Override protected void reduce(Text key, Iterable<Text> values, Context context) throws IOException, InterruptedException { int N = context.getConfiguration().getInt("topn", 5); //获取输入的TopN的长度 TreeMap<Integer,String> map = new TreeMap<>(); for(IntWritable value : values){ map.put(value.get(),""); if (map.size() > N) { map.remove(map.firstKey()); } } } protected void cleanup(Context context) throws IOException, InterruptedException { for (Integer i : map.descendingMap().keySet()) { context.write(NullWritable.get(), new IntWritable(i)); } } } public static void main(String[] args) throws Exception { Configuration conf = new Configuration();//设置MapReduce的配置 conf.setInt("topn",5); String[] otherArgs = new GenericOptionsParser(conf,args).getRemainingArgs(); if(otherArgs.length < 2){ System.out.println("Usage: SortedTopN <in> [<in>...] <out>"); System.exit(2); } //设置作业 //Job job = new Job(conf); Job job = Job.getInstance(conf); job.setJarByClass(SortedTopN.class); job.setJobName("SortedTopN"); //设置处理map,reduce的类 job.setMapperClass(SortedTopNMapper.class); job.setReducerClass(SortedTopNReducer.class); //设置输入输出格式的处理 job.setOutputKeyClass(Text.class); job.setOutputValueClass(Text.class); //设定输入输出路径 for (int i = 0; i < otherArgs.length-1;++i){ FileInputFormat.addInputPath(job,new Path(otherArgs[i])); } FileOutputFormat.setOutputPath(job, new Path(otherArgs[otherArgs.length-1])); System.exit(job.waitForCompletion(true)?0:1); } }