天天看點

topk問題java,hadoop1-TopK問題實作

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