MapReduce數據分析(2)二次排序

二、MapReduce 第二講Secondary sort(二次排序)

接下來,我們先講一下二次排序的原理。

MR默認會對鍵進行排序,然而有的時候我們也有對值進行排序的需求。滿足這種需求一是可以再reduce階段排序收集過來的values,但是,如果有數量巨大的values可能就導致數據溢出等問題,這就是二次排序應用的場景——————將對值的排序也安排到MR計算過程之中,而不是單獨來做。

二次排序就是首先按照第一字段排序,然後再對第一字段相同的行按照第二軸端排序,注意不能破壞第一次排序的結果。

好了 下面話不多少,直接上程序。

原始數據:

在這裏插入圖片描述
demo:二次排序
需求:第一列正序,第二列倒序。
代碼如下:
副類

//自定義類

package sort;

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

import org.apache.hadoop.io.WritableComparable;
 //自己定義的key類應該實現WritableComparable接口
public class inpart extends Object implements WritableComparable<inpart>{
	//定義兩個變量 
	private int frist;
	private int second;
	/*這裏需要注意一下! 這個方法必須添加否則會報錯。
	public inpart() {
		
	}
	*/
	
	public inpart(int frist, int second) {
	
		this.frist = frist;
		this.second = second;
	}
	
	  //反序列化,從流中的二進制轉換成InPart
	public void readFields(DataInput in) throws IOException {
		frist=in.readInt();
		second=in.readInt();
		
	}
	 //序列化,將InPart轉化成使用流傳送的二進制
	public void write(DataOutput out) throws IOException {
		// TODO Auto-generated method stub
		out.writeInt(frist);
		out.writeInt(second);
	}
	public int getFrist() {
		return frist;
	}
	public void setFrist(int frist) {
		this.frist = frist;
	}
	public int getSecond() {
		return second;
	}
	public void setSecond(int second) {
		this.second = second;
	}
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + frist;
		result = prime * result + second;
		return result;
	}
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		inpart other = (inpart) obj;
		if (frist != other.frist)
			return false;
		if (second != other.second)
			return false;
		return true;
	}
	public int compareTo(inpart o) {
		//第一列正序排列
		int cmp = this.frist-o.frist;
		if (cmp!=0) {
			return cmp;
		}
		//第二列倒序排列
		return o.second-this.second;
	}
	
	public String toString() {
		return frist+"\t"+second;
	}
	
}

主類

package sort;

import java.io.IOException;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.NullWritable;
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 sort{

	public static void main(String[] args) throws Exception {
		Configuration conf=new Configuration();
		Job job = Job.getInstance(conf);
		job.setJarByClass(sort.class);
		job.setMapperClass(MMapper.class);
		job.setReducerClass(MReduce.class);
		job.setMapOutputKeyClass(inpart.class);
		job.setMapOutputValueClass(NullWritable.class);
		job.setOutputKeyClass(inpart.class);
		job.setOutputValueClass(NullWritable.class);
		FileInputFormat.setInputPaths(job, new Path(args[0]));
		FileOutputFormat.setOutputPath(job, new Path(args[1]));
		job.waitForCompletion(true);
	}

	public static class MMapper extends Mapper<LongWritable, Text, inpart, NullWritable>{

		@Override
		protected void map(LongWritable key, Text value, Context context)
				throws IOException, InterruptedException {
				//轉換數據類型並切割
			String[] line = value.toString().split("\t");
			int one = Integer.parseInt(line[0]);
			int two = Integer.parseInt(line[1]);
			//寫入
			context.write(new inpart(one,two), NullWritable.get());
		}

	}
	public static class MReduce extends Reducer<inpart, NullWritable, inpart, NullWritable>{
	
		@Override
		protected void reduce(inpart key, Iterable<NullWritable> value,
				Context context)
				throws IOException, InterruptedException {
					//這裏直接寫出
			context.write(key, NullWritable.get());
		}
	}

}

運行結果:

在這裏插入圖片描述
下面附上數據:

7	444
3	9999
7	333
4	22
3	7777
7	555
3	6666
6	0
3	8888
4	11	

本次的教程到次結束,有什麼不會不懂的地方下方留言。
!!!多多支持博主!!!。

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章