温度排序之二次排序
描述
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-4级
2016 35 2016-06-19 35 21 晴~多云 东南风 小于3级转3-4级
2016 34 2016-06-25 34 20 晴 西南风 小于3级转3-4级
2016 34 2016-08-14 34 22 晴 东南风 2级
2016 34 2016-07-11 34 25 多云~阴 Null 小于3级转3-4级
2016 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-4级
2013 35 2013-08-08 35 23 晴 西北风 小于3级转3-4级
2013 35 2013-07-23 35 22 晴 西风 小于3级转3-4级
2013 35 2013-07-24 35 23 晴 西南风 小于3级转3-4级
2013 34 2013-08-14 34 25 多云 西南风 小于3级转3-4级
2013 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-4级
2015 36 2015-07-14 36 23 多云~阴 东南风 小于3级转3-4级
2015 35 2015-08-12 35 22 晴 东南风 小于3级转3-4级
2015 34 2015-07-26 34 24 多云 东南风 小于3级转3-4级
2015 34 2015-07-15 34 22 多云 东南风 小于3级转3-4级
2015 34 2015-05-26 34 20 晴~ 西南风 小于3级转3-4级