【Hadoop】MapReduce温度排序之二次排序

温度排序之二次排序

描述

1、计算2011年到2016年每年温度最高的时间

2、计算每年温度最高前十天

思路

1、按照年份升序排序,同时每一年中温度降序排序。

2、按照年份分组,每一年对应一个reduce任务

3、mapper输出,key为封装对象。

目的

1、自定排序

2、自定义分区

3、自定义分组

示例

测试数据 格式

2016-10-01  26  15  多云  南风  1级  
2016-10-02  25  15  多云  南风  2级  
2016-10-03  28  17  多云  东风  3级  
2016-10-04  19  12  阴   东风  3级  
2016-10-05  23  10  晴   西南风 2级  
2016-10-06  19  12  多云  东南风 3级  
2016-10-07  17  8   小雨  西南风 2级  
2016-10-08  18  3   晴   东北风 2级  

注:数据为真实数据,用Python从http://lishi.tianqi.com/抓取的。
Python代码查看另一篇博客查看

封装对象


package com.mr;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;

import org.apache.hadoop.io.WritableComparable;

//封装为对象

public class KeyPair implements WritableComparable<KeyPair>{

    private int year;   //年份
    private int hot;    //温度

    public int getYear() {
        return year;
    }
    public void setYear(int year) {
        this.year = year;
    }
    public int getHot() {
        return hot;
    }
    public void setHot(int hot) {
        this.hot = hot;
    }
    //序列化
    public void readFields(DataInput in) throws IOException {
        this.year = in.readInt();
        this.hot = in.readInt();
    }
    //反序列化
    public void write(DataOutput out) throws IOException {
        out.writeInt(year);
        out.writeInt(hot);
    }
    //比较
    public int compareTo(KeyPair o) {
        int ret = Integer.compare(year, o.getYear());
        if(ret != 0){
            return ret;
        }
        return Integer.compare(hot, o.getHot());
    }

    public int hashCode() {
        return new Integer(year + hot).hashCode();
    }

    public String toString() {
        return year + "\t" + hot;
    }
}

自定排序


package com.mr;

import org.apache.hadoop.io.WritableComparable;
import org.apache.hadoop.io.WritableComparator;

//自定义排序

public class SortHot extends WritableComparator{

        public SortHot() {
            super(KeyPair.class, true);
        }

        @Override
        public int compare(WritableComparable a, WritableComparable b) {
            KeyPair o1 = (KeyPair) a;
            KeyPair o2 = (KeyPair) b;

            int res = Integer.compare(o1.getYear(), o2.getYear());
            if(res != 0){
                return res;
            }
            return -Integer.compare(o1.getHot(), o2.getHot());
        }
}

自定义分区

package com.mr;

import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Partitioner;

//自定义分区

public class FirstPartiotion extends Partitioner<KeyPair, Text>{

    @Override
    public int getPartition(KeyPair key, Text value, int num) {
        return (key.getYear() * 127) % num;
    }

}

自定义分组


package com.mr;

import org.apache.hadoop.io.WritableComparable;
import org.apache.hadoop.io.WritableComparator;

//自定义分组

public class GroupHot extends WritableComparator{

    public GroupHot() {
        super(KeyPair.class, true);
    }

    @Override
    public int compare(WritableComparable a, WritableComparable b) {
        KeyPair o1 = (KeyPair) a;
        KeyPair o2 = (KeyPair) b;
        return Integer.compare(o1.getYear(), o2.getYear());
    }
}

MapReduce

package com.mr;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
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;


public class RunJob {

    public static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

    //Mapper 类
    static class HotMapper extends Mapper<LongWritable, Text, KeyPair, Text>{

        protected void map(LongWritable key, Text value, Context context) 
                throws java.io.IOException ,InterruptedException {

            String line = value.toString();

            String[] ss = line.split("\t");

            if(ss.length == 6){
                try {
                    Date date = sdf.parse(ss[0]);
                    Calendar c = Calendar.getInstance();
                            c.setTime(date);
                    int year = c.get(1);//year值的格式为2016
                    String hot = ss[1]);

                    KeyPair kp = new KeyPair();
                    kp.setYear(year);
                    kp.setHot(Integer.parseInt(hot));

                    context.write(kp, value);
                } catch (ParseException e) {
                    e.printStackTrace();
                }
            }
        };
    } 

    //reduce 类
    static class HotReducer extends Reducer<KeyPair, Text, KeyPair, Text>{  
        protected void reduce(KeyPair key, Iterable<Text> values, Context context) 
                throws java.io.IOException ,InterruptedException {

            for(Text value : values){
                context.write(key, value);
            }

        };
    }

    public static void main(String[] args) {    
        Configuration conf = new Configuration();
        try {
            Job job = new Job(conf);
            job.setJobName("Hot");

            job.setJarByClass(RunJob.class);

            job.setMapperClass(HotMapper.class);

            job.setReducerClass(HotReducer.class);
            job.setMapOutputKeyClass(KeyPair.class);
            job.setMapOutputValueClass(Text.class);
            //设置每一年对应一个reduce任务
            job.setNumReduceTasks(6);
            //自定义分区
            job.setPartitionerClass(FirstPartiotion.class); 
            //自定义分区
            job.setSortComparatorClass(SortHot.class);  
            //自定义分组
            job.setGroupingComparatorClass(GroupHot.class);

            FileInputFormat.addInputPath(job, new Path("/user/hadoop/input/hot/"));
            FileOutputFormat.setOutputPath(job, new Path("/user/hadoop/hot"));

            System.exit(job.waitForCompletion(true) ? 0 : 1);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

输出目录

[hadoop@Master ~]$ hdfs dfs -ls /user/hadoop/hot
Found 7 items
-rw-r--r--   3 hadoop supergroup          0 2016-12-03 23:14 /user/hadoop/hot/_SUCCESS
-rw-r--r--   3 hadoop supergroup      17509 2016-12-03 23:13 /user/hadoop/hot/part-r-00000
-rw-r--r--   3 hadoop supergroup      20671 2016-12-03 23:12 /user/hadoop/hot/part-r-00001
-rw-r--r--   3 hadoop supergroup      22570 2016-12-03 23:13 /user/hadoop/hot/part-r-00002
-rw-r--r--   3 hadoop supergroup      22810 2016-12-03 23:12 /user/hadoop/hot/part-r-00003
-rw-r--r--   3 hadoop supergroup      22083 2016-12-03 23:13 /user/hadoop/hot/part-r-00004
-rw-r--r--   3 hadoop supergroup      22548 2016-12-03 23:14 /user/hadoop/hot/part-r-00005

输出结果

//查看一部分数据
[hadoop@Master ~]$ hdfs dfs -cat hot/part-r-00000 | head -n6
2016    35  2016-06-26  35  22  晴~多云   西南风 小于3级转3-42016    35  2016-06-19  35  21  晴~多云   东南风 小于3级转3-42016    34  2016-06-25  34  20  晴   西南风 小于3级转3-42016    34  2016-08-14  34  22  晴   东南风 22016    34  2016-07-11  34  25  多云~阴   Null    小于3级转3-42016    34  2016-07-10  34  25  晴~多云   Null    小于3级转3-4级

[hadoop@Master ~]$ hdfs dfs -cat hot/part-r-00003 | head -n6
2013    35  2013-07-02  35  22  晴   西南风 小于3级转3-42013    35  2013-08-08  35  23  晴   西北风 小于3级转3-42013    35  2013-07-23  35  22  晴   西风  小于3级转3-42013    35  2013-07-24  35  23  晴   西南风 小于3级转3-42013    34  2013-08-14  34  25  多云  西南风 小于3级转3-42013    34  2013-08-16  34  26  中雨转多云   西北风 小于3级转3-4级

[hadoop@Master ~]$ hdfs dfs -cat hot/part-r-00005 | head -n6
2015    37  2015-07-13  37  23  晴~多云   东南风 小于3级转3-42015    36  2015-07-14  36  23  多云~阴   东南风 小于3级转3-42015    35  2015-08-12  35  22  晴   东南风 小于3级转3-42015    34  2015-07-26  34  24  多云  东南风 小于3级转3-42015    34  2015-07-15  34  22  多云  东南风 小于3级转3-42015    34  2015-05-26  34  20  晴~ 西南风 小于3级转3-4
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值