1、對于排名,一般都是很熱衷的,那麼如何實作在資料量多的情況下,得到所需要的資料呢,選取前幾名的實際應用中,也會有許多,形成統一的算法實作,比着參考就可以了。
2、資料檔案a.txt:
2
4
6
7
9
6
4
3、輸出資料為(例如取前三名,前面為資料,後面為名次,名次可通過輸入參數配置):
9 1
7 2
6 3
4、設計思路:
Map端:
1)因為是topK問題,自然想到可以自己設計key,重寫比較方法,按自己所想要的比較方法實作即可。
2)map端輸出,僅需輸出最後的n個最大數即可,是以需要在最後的那個cleanup方法裡實作,通過一個成員變量list儲存資料。
3)最後輸出此list中的資料即可
4)list為自定義的一個容器,在往裡面添加元素的時候,會進行比較。
5)在這個例子中,沒有使用list,而是直接采用map的suffle對key進行的排序。一個map的輸出量會很多。下一篇優化裡面使用了list
Reduce端:
1) 類似一個map,隻針對key進行處理即可,輸出前n的數值(此n個key已是經過suffle排過序的,取前n個即可,其它丢棄)。
5、程式實作:
package test;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.io.WritableComparable;
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;
import org.apache.hadoop.util.GenericOptionsParser;
public class TopK {
public static class Map extends Mapper{
//此處可以進行優化,隻需輸出此map處理的最大的那幾個值即可。
protected void map(Object key, Text value, Context context)
throws java.io.IOException ,InterruptedException {
try {
int num = Integer.parseInt(value.toString());
context.write(new MyKey(num), NullWritable.get());
} catch (Exception e) {
// TODO: handle exception
return ;
}
};
}
public static class Reduce extends Reducer{
private static Text k = new Text();
//預設值,擷取的個數
private static int count = 5;
//開始值
private static int start = 1;
//初始化時擷取配置的參數
protected void setup(Context context)
throws IOException ,InterruptedException {
//取得配置的參數,需要擷取幾個值
count = Integer.parseInt(context.getConfiguration().get("top_num"));
};
protected void reduce(MyKey key, Iterable values, Context context)
throws IOException ,InterruptedException {
//因為key是排序過來的,是以輸出count個值就可以了
if(start <= count){
k.set(key.getNum()+"\t"+start);
context.write(k, NullWritable.get());
start++;
}
};
}
public static void main(String[] args) throws Exception {
Configuration conf = new Configuration();
String[] otherArgs = new GenericOptionsParser(conf,args).getRemainingArgs();
if(otherArgs.length != 3){
System.err.println("Usage:TopK");
System.exit(2);
}
//參數3 為要擷取的最大個數
conf.set("top_num", args[2]);
Job job = new Job(conf, "TopK");
job.setJarByClass(TopK.class);
job.setMapperClass(Map.class);
job.setReducerClass(Reduce.class);
job.setMapOutputKeyClass(MyKey.class);
job.setMapOutputValueClass(NullWritable.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(NullWritable.class);
FileInputFormat.addInputPath(job, new Path(args[0]));
FileOutputFormat.setOutputPath(job, new Path(args[1]));
System.exit(job.waitForCompletion(true) ? 0 : 1);
}
private static class MyKey implements WritableComparable{
private int num;
public int getNum() {
return num;
}
public MyKey() {
}
public MyKey(int num) {
super();
this.num = num;
}
@Override
public void readFields(DataInput in) throws IOException {
// TODO Auto-generated method stub
num = in.readInt();
}
@Override
public void write(DataOutput out) throws IOException {
// TODO Auto-generated method stub
out.writeInt(num);
}
@Override
public int compareTo(MyKey o) {
// TODO Auto-generated method stub
//反序輸出
return o.num - this.num;
}
}
}
計算結果:
9 1
7 2
6 3
原文:http://www.cnblogs.com/jsunday/p/3807326.html