hadoop2.6温度统计mapreduce程序

来源:互联网 发布:java 驼峰转下划线 编辑:程序博客网 时间:2024/04/29 20:44

初涉hadoop,在看完hadoop温度统计例子后,记下自己的理解,搭建hadoop集群可以参考给力星的博客
数据格式如下:
1949-10-01 14:21:01 34°C
1949-10-02 14:21:01 36°C
1950-01-01 11:21:01 32°C
1950-10-01 12:21:01 37°C
1951-12-01 12:21:01 23°C
1950-10-01 12:21:01 41°C
1950-12-01 12:21:01 27°C
1951-12-01 12:21:01 45°C
1951-12-01 12:21:01 46°C
目的:
1、计算在1949——1955,每年温度最高的时间
2、计算在1949——1955,每年温度最高的前10天
主程序写在RunJob类中,此类包含map和reduce两个静态类,当然也可以抽出来写啦,map类作为接受输入的分片,先看一张图
mapreduce工作流
输入的分片整个文件作为key,其中的文本作为value,然后在map函数中对其中的文本进行处理,在此程序中,对接收到的spilt,每行的数据会对应到写好的KeyPair中进行组织,这里的keyPair是自己写的数据的组织方式,对温度数据中的温度和年份进行组织,方便排序,接下来需要进行分区排序和分组

public class RunJob {    public static SimpleDateFormat SDF = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");    static class HotMapper extends Mapper<LongWritable, Text,KeyPair, Text>{        //重写map方法        protected void map(LongWritable key, Text value, Context context)                throws IOException, InterruptedException {            String line = value.toString();            String[] ss = line.split("\t");            if(ss.length==2){                try {                    Date date = SDF.parse(ss[0]);                    Calendar c = Calendar.getInstance();                    c.setTime(date);                    int year = c.get(1);                    String hot = ss[1].substring(0, ss[1].indexOf("°C"));                    KeyPair kp = new KeyPair();                    kp.setYear(year);                    kp.setHot(Integer.parseInt(hot));                    context.write(kp, value);                } catch (Exception e) {                    e.printStackTrace();                }            }        }    }    static class HotReduce extends Reducer<KeyPair, Text, KeyPair, Text>{        @Override        protected void reduce(KeyPair key, Iterable<Text> value, Context context)                throws IOException, InterruptedException {            for(Text v : value){                context.write(key, v);            }        }    }    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(HotReduce.class);            job.setMapOutputKeyClass(KeyPair.class);            job.setMapOutputValueClass(Text.class);            job.setNumReduceTasks(3);            job.setPartitionerClass(FirstPartitioner.class);            job.setSortComparatorClass(SortHot.class);            job.setGroupingComparatorClass(GroupHot.class);            FileInputFormat.addInputPath(job, new Path("/usr/input/hot"));            FileOutputFormat.setOutputPath(job, new Path("/usr/output/hot"));            System.exit(job.waitForCompletion(true)?  0 : 1);        } catch (Exception e) {            e.printStackTrace();        }    }}

KeyPair类是数据的java bean类,方便对数据进行分区和排序

//封装类,封装温度和年份为一个对象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 {        // 通过rpc协议读取二进制数据流,反序列化的过程        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) {        // 比较year的值 相等则res为0,        int res = Integer.compare(year, o.getYear());        if(res != 0){            return res;        }        return Integer.compare(hot, o.getHot());    }    @Override    public String toString(){        return year  + "\t" + hot;    }    @Override    public int hashCode() {        return new Integer(year+hot).hashCode();    }}

接下来是paratition操作的重写,上文写好的keypair类传进来,根据相同的年份进行分区

//自定义分区public class FirstPartitioner extends Partitioner<KeyPair, Text>{    public int getPartition(KeyPair key, Text value, int number) {        //年份相同的划分在一个分区,年份相同的返回的结果一定相同        return (key.getYear()*127)%number;    }}

然后重写排序方法sort,这里主要需要重写compare方法,直接调用integer的compare方法

//温度排序的类public class SortHot extends WritableComparator{    public SortHot() {        super(KeyPair.class,true);    }    //重写比较的方法 ,自定义排序    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());    }}

最后重写分组方法,这里的分组是最后进行组合的过程

public class GroupHot extends WritableComparator{    public GroupHot() {        super(KeyPair.class,true);    }    public int compare(WritableComparable a, WritableComparable b) {        KeyPair o1 = (KeyPair) a;        KeyPair o2 = (KeyPair) b;        //年份相同则返回为同一个组        return Integer.compare(o1.getYear(), o2.getYear());    }}

到此为止,程序就结束啦 ,仅供参考

0 0