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);
    }
}

 

posted on 2020-05-16 15:56  hdc520  阅读(1191)  评论(0编辑  收藏  举报

导航