• 使用Partitioner实现输出到多个文件


    1、需求

      按学生的年龄段,将数据输出到不同的文件。这里我们分为三个年龄段:小于等于20岁、大于20岁小于等于50岁和大于50岁

    2、实现

      1、编写Partitioner,代码如下

    public static class StudentPartitioner extends Partitioner<IntWritable, Text> {
        @Override
        public int getPartition(IntWritable key, Text value, int numReduceTasks) {
            // 学生年龄
            int ageInt = key.get();
            
            // 默认指定分区 0
            if (numReduceTasks == 0)
                return 0;    
    
            if (ageInt <= 20) { // 年龄小于等于20,指定分区0
                return 0;
            }else if (ageInt <= 50) { // 年龄大于20,小于等于50,指定分区1
                return 1;
            }else{ // 剩余年龄,指定分区2
                return 2;
            }
        }
    }

      2、编写mapper

    public static class StudentMapper extends Mapper<LongWritable, Text, IntWritable, Text>{
        @Override
        protected void map(LongWritable key, Text value,Context context) throws IOException, InterruptedException {
            String[] studentArr = value.toString().split("	");
            
            if(StringUtils.isNotBlank(studentArr[1])){
                /*
                 * 姓名    年龄(中间以tab分割)
                 * 张明明    45
                 */
                // 年龄
                IntWritable pKey = new IntWritable(Integer.parseInt(studentArr[1].trim()));
                
                // 以年龄作为key输出
                context.write(pKey, value);
            }
        }
    }

      3、编写reducer

    public static class StudentReducer extends Reducer<IntWritable, Text, NullWritable, Text> {
        @Override
        protected void reduce(IntWritable key, Iterable<Text> values,Context context) throws IOException, InterruptedException {
            for(Text value : values){
                context.write(NullWritable.get(), value);
            }
        }
    }

      4、一些运行代码

    @Override
    public int run(String[] arg0) throws Exception {
        // 读取配置文件
        Configuration conf = new Configuration();
        
        Path mypath = new Path(arg0[1]);
        FileSystem hdfs = mypath.getFileSystem(conf);
        if (hdfs.isDirectory(mypath)) {
            hdfs.delete(mypath, true);
        }
        
        // 新建一个任务
        Job job = new Job(conf, "PartitionerDemo");
        // 设置主类
        job.setJarByClass(StudentPartitioner.class);
        
        // 输入路径
        FileInputFormat.addInputPath(job, new Path(arg0[0]));
        // 输出路径
        FileOutputFormat.setOutputPath(job, new Path(arg0[1]));
        
        // Mapper
        job.setMapperClass(StudentMapper.class);
        // Reducer
        job.setReducerClass(StudentReducer.class);
        
        // mapper输出格式
        job.setMapOutputKeyClass(IntWritable.class);
        job.setMapOutputValueClass(Text.class);
        
        // reducer输出格式
        job.setOutputKeyClass(NullWritable.class);  
        job.setOutputValueClass(Text.class); 
            
        //设置Partitioner类
         job.setPartitionerClass(StudentPartitioner.class);
         // reduce个数设置为3
        job.setNumReduceTasks(3);
        
        //提交任务
        return job.waitForCompletion(true)?0:1;
    }
    public static void main(String[] args0) throws Exception {
        // 数据输入路径和输出路径
    //    String[] args0 = {
    //        "hdfs://ljc:9000/buaa/student/student.txt",
    //        "hdfs://ljc:9000/buaa/student/out/"
    //    };
        int ec = ToolRunner.run(new Configuration(), new StudentAgePartitionerDemo(), args0);
        System.exit(ec);
    }

    3、总结

      Partitioner适用于事先知道分区数的情况下,比如像上面这个需求

      缺点:

        1、在作业运行之前需要知道分区数,也就是年龄段的个数,如果分区数未知,就无法操作。

        2、一般来说,让应用程序来严格限定分区数并不好,因为可能导致分区数少或分区不均

    如果,您认为阅读这篇博客让您有些收获,不妨点击一下右下角的【推荐】。
    如果,您希望更容易地发现我的新博客,不妨点击一下左下角的【关注我】。
    如果,您对我的博客所讲述的内容有兴趣,请继续关注我的后续博客,我是【刘超★ljc】。

    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

    实现代码及数据:下载

  • 相关阅读:
    FastApi下载文件
    测试平台系列(74) 测试计划定时执行初体验
    [CF895C]Square Subsets
    [bzoj2157/lgoj1505]旅游
    [luogu3674]小清新人渣的本愿
    关于Web前端 编程时流程控制中的流程控制图和 if 判断及九九乘法表
    关于流程控制语句中switch选择和各种循环
    SUSE Linux Enterprise Server 11 SP3安装详解(转)
    SVN代码管理
    安卓app开发服务器端开发
  • 原文地址:https://www.cnblogs.com/codeOfLife/p/5452037.html
Copyright © 2020-2023  润新知