hadoop?詳解如何實(shí)現(xiàn)數(shù)據(jù)排序
排序是Hadoop的默認(rèn)行為,不管你是否需要,MapReduce的MapTask和Task都會(huì)對(duì)輸出的結(jié)果的Key進(jìn)行排序,默認(rèn)的排序順序是按照字典順序排列,實(shí)現(xiàn)的方法是快速排序。
自定義排序需要繼承WritableComparable,實(shí)現(xiàn)compareTo方法就完成了自定義排序。
下面介紹幾種排序的場(chǎng)景
一、全排序
全排序是指最終只產(chǎn)生一個(gè)輸出文件,數(shù)據(jù)在文件內(nèi)部有序。
1、輸入數(shù)據(jù)
13470253144 180 180 360 13509468723 7335 110349 117684 13560439638 918 4938 5856 13568436656 3597 25635 29232 13590439668 1116 954 2070 13630577991 6960 690 7650 13682846555 1938 2910 4848 13729199489 240 0 240 13736230513 2481 24681 27162 13768778790 120 120 240 13846544121 264 0 264 13956435636 132 1512 1644 13966251146 240 0 240 13975057813 11058 48243 59301 13992314666 3008 3720 6728 15043685818 3659 3538 7197 15910133277 3156 2936 6092 15959002129 1938 180 2118 18271575951 1527 2106 3633 18390173782 9531 2412 11943 84188413 4116 1432 5548
2、Bean對(duì)象
繼承WritabelComparable,并實(shí)現(xiàn)方法compareTo。WritabelComparable起始就是兩個(gè)接口的綜合,Writable是Hadoop自定義序列化數(shù)據(jù)需要實(shí)現(xiàn)的接口,而Coparable是比較排序需要實(shí)現(xiàn)的接口。
package cn.nuwa.hap.cp;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.hadoop.io.Writable;
import org.apache.hadoop.io.WritableComparable;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
@Data
@NoArgsConstructor
public class FlowBean implements WritableComparable<FlowBean> {
private long upFlow; //上行流量
private long downFlow; //下行流量
private long sumFlow; //總流量
public void setSumFlow() {
this.sumFlow = this.upFlow + this.downFlow;
}
//4 實(shí)現(xiàn)序列化和反序列化方法,注意順序一定要保持一致
@Override
public void write(DataOutput dataOutput) throws IOException {
dataOutput.writeLong(upFlow);
dataOutput.writeLong(downFlow);
dataOutput.writeLong(sumFlow);
}
@Override
public void readFields(DataInput dataInput) throws IOException {
this.upFlow = dataInput.readLong();
this.downFlow = dataInput.readLong();
this.sumFlow = dataInput.readLong();
}
//5 重寫(xiě)ToString
@Override
public String toString() {
return upFlow + "\t" + downFlow + "\t" + sumFlow;
}
@Override
public int compareTo(FlowBean o) {
//按照總流量比較,倒序排列
if(this.sumFlow > o.getSumFlow()){
return -1;
}else if(this.sumFlow < o.getSumFlow()){
return 1;
}else {
return 0;
}
}
}
3、Mapper類(lèi)
package cn.nuwa.hap.cp;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;
import java.io.IOException;
public class FlowMapper extends Mapper<LongWritable, Text, FlowBean, Text> {
private FlowBean outK = new FlowBean();
private Text outV = new Text();
@Override
protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
//1 獲取一行數(shù)據(jù)
String line = value.toString();
//2 按照"\t",切割數(shù)據(jù)
String[] split = line.split("\t");
//3 封裝outK outV
outK.setUpFlow(Long.parseLong(split[1]));
outK.setDownFlow(Long.parseLong(split[2]));
outK.setSumFlow();
outV.set(split[0]);
//4 寫(xiě)出outK outV
context.write(outK,outV);
}
}
4、Reduce類(lèi)
package cn.nuwa.hap.cp;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;
import java.io.IOException;
public class FlowReducer extends Reducer<FlowBean, Text, Text, FlowBean> {
@Override
protected void reduce(FlowBean key, Iterable<Text> values, Context context) throws IOException, InterruptedException {
//遍歷values集合,循環(huán)寫(xiě)出,避免總流量相同的情況
for (Text value : values) {
//調(diào)換KV位置,反向?qū)懗?
context.write(value, key);
}
}
}
5、Dirver類(lèi)
package cn.nuwa.hap.cp;
import cn.nuwa.hap.wb.FlowBean;
import cn.nuwa.hap.wb.ProvincePartitioner;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import java.io.IOException;
public class FlowDriver {
public static void main(String[] args) throws IOException, InterruptedException, ClassNotFoundException {
//1 獲取job對(duì)象
Configuration conf = new Configuration();
Job job = Job.getInstance(conf);
//2 關(guān)聯(lián)本Driver類(lèi)
job.setJarByClass(FlowDriver.class);
//3 關(guān)聯(lián)Mapper和Reducer
job.setMapperClass(FlowMapper.class);
job.setReducerClass(FlowReducer.class);
//4 設(shè)置Map端輸出KV類(lèi)型
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(cn.nuwa.hap.wb.FlowBean.class);
//5 設(shè)置程序最終輸出的KV類(lèi)型
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(FlowBean.class);
//6 設(shè)置程序的輸入輸出路徑
FileInputFormat.setInputPaths(job, new Path("C:\\Users\\Dell\\Desktop\\hadoop\\inputFlow"));
FileOutputFormat.setOutputPath(job, new Path("C:\\Users\\Dell\\Desktop\\hadoop\\outputFlow"));
//8 指定自定義分區(qū)器
job.setPartitionerClass(ProvincePartitioner.class);
//9 同時(shí)指定相應(yīng)數(shù)量的ReduceTask
job.setNumReduceTasks(5);
//7 提交Job
boolean b = job.waitForCompletion(true);
System.exit(b ? 0 : 1);
}
}
6、最終結(jié)果
13509468723 7335 110349 117684 13975057813 11058 48243 59301 13568436656 3597 25635 29232 13736230513 2481 24681 27162 18390173782 9531 2412 11943 13630577991 6960 690 7650 15043685818 3659 3538 7197 13992314666 3008 3720 6728 15910133277 3156 2936 6092 13560439638 918 4938 5856 84188413 4116 1432 5548 13682846555 1938 2910 4848 18271575951 1527 2106 3633 15959002129 1938 180 2118 13590439668 1116 954 2070 13956435636 132 1512 1644 13470253144 180 180 360 13846544121 264 0 264 13729199489 240 0 240 13768778790 120 120 240 13966251146 240 0 240
二、分區(qū)排序
分區(qū)排序的本質(zhì)是:
- 數(shù)據(jù)分區(qū)
- 區(qū)內(nèi)數(shù)據(jù)有序
只需要在全排序的基礎(chǔ)上加上分區(qū)的代碼即可
1、分區(qū)類(lèi)
package cn.nuwa.hap.cp;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Partitioner;
public class ProvincePartitioner extends Partitioner< FlowBean, Text> {
@Override
public int getPartition(FlowBean flowBean, Text text, int numPartitions) {
//獲取手機(jī)號(hào)前三位
String phone = text.toString();
String prePhone = phone.substring(0, 3);
//定義一個(gè)分區(qū)號(hào)變量partition,根據(jù)prePhone設(shè)置分區(qū)號(hào)
int partition;
if("136".equals(prePhone)){
partition = 0;
}else if("137".equals(prePhone)){
partition = 1;
}else if("138".equals(prePhone)){
partition = 2;
}else if("139".equals(prePhone)){
partition = 3;
}else {
partition = 4;
}
//最后返回分區(qū)號(hào)partition
return partition;
}
}
2、Driver類(lèi)新增分區(qū)配置
// 設(shè)置自定義分區(qū)器 job.setPartitionerClass(ProvincePartitioner.class); // 設(shè)置對(duì)應(yīng)的ReduceTask的個(gè)數(shù) job.setNumReduceTasks(5);
3、結(jié)果

part-r-00000
13630577991 6960 690 7650 13682846555 1938 2910 4848
part-r-00001
13736230513 2481 24681 27162 13729199489 240 0 240 13768778790 120 120 240
part-r-00002
13846544121 264 0 264
part-r-00003
13975057813 11058 48243 59301 13992314666 3008 3720 6728 13956435636 132 1512 1644 13966251146 240 0 240
part-r-00004
13509468723 7335 110349 117684 13568436656 3597 25635 29232 18390173782 9531 2412 11943 15043685818 3659 3538 7197 15910133277 3156 2936 6092 13560439638 918 4938 5856 84188413 4116 1432 5548 18271575951 1527 2106 3633 15959002129 1938 180 2118 13590439668 1116 954 2070 13470253144 180 180 360
到此這篇關(guān)于hadoop 詳解如何實(shí)現(xiàn)數(shù)據(jù)排序的文章就介紹到這了,更多相關(guān)hadoop 數(shù)據(jù)排序內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java如何取掉json數(shù)據(jù)中值為null的屬性字段
這篇文章主要介紹了Java如何取掉json數(shù)據(jù)中值為null的屬性字段,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03
手把手教你如何在idea中搭建SpringBoot項(xiàng)目
這篇文章主要介紹了如何搭建一個(gè)SpringBoot項(xiàng)目,包括環(huán)境準(zhǔn)備、創(chuàng)建新項(xiàng)目、探索項(xiàng)目結(jié)構(gòu)以及展望未來(lái),通過(guò)詳細(xì)的步驟和實(shí)用的技巧,幫助開(kāi)發(fā)者快速上手SpringBoot開(kāi)發(fā),文中通過(guò)圖文介紹的非常詳細(xì),需要的朋友可以參考下2025-02-02
Mybatis中的游標(biāo)查詢(xún)Cursor(滾動(dòng)查詢(xún))
這篇文章主要介紹了Mybatis中的游標(biāo)查詢(xún)Cursor(滾動(dòng)查詢(xún)),具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01
Spring Boot中使用JDBC Templet的方法教程
這篇文章主要給大家介紹了關(guān)于在Spring Boot中使用JDBC Templet的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。2018-03-03
SpringBoot如何配置MySQL和Oracl雙數(shù)據(jù)源(Mybatis)
這篇文章主要介紹了SpringBoot如何配置MySQL和Oracl雙數(shù)據(jù)源(Mybatis)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-03-03
java使用jdbc連接數(shù)據(jù)庫(kù)簡(jiǎn)單實(shí)例
這篇文章主要為大家詳細(xì)介紹了java使用jdbc連接數(shù)據(jù)庫(kù)的簡(jiǎn)單實(shí)例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-07-07
java中的equals()和toString()方法實(shí)例詳解
這篇文章主要介紹了java中的equals()和toString()方法實(shí)例詳解的相關(guān)資料,這里舉例說(shuō)明,并附實(shí)例代碼,和實(shí)現(xiàn)效果圖,需要的朋友可以參考下2016-11-11

