查找数据集中的Top-K记录

时间:2012-02-08 22:18:16

标签: java hadoop mapreduce

在尝试学习Hadoop时,我正在练习“Hadoop in Action”一书中未解决的编程问题

数据集示例:

  

3070801,1963,1096 ,, “BE”, “” ,, 1,269,6,69,1,...,0 ,,,,,,,   3070802,1963,1096 ,, “美国”, “TX” ,, 1,2,6,63,0 ,,,,,,,,,   3070803,1963,1096 ,, “US”, “IL” ,, 1,2,6,63,...,9,0.3704 ,,,,,,,   3070804,1963,1096 ,, “US”, “OH” ,, 1,2,6,63,3日,0.6667 ,,,,,,,   3070805,1963,1096 ,, “美国”, “CA” ,, 1,2,6,63,1,0 ,,,,,,,   3070806,1963,1096 ,, “美国”, “PA” ,, 1,2,6,63,0 ,,,,,,,,,   3070807,1963,1096 ,, “US”, “OH” ,, 1,623,3,39,3日,0.4444 ,,,,,,,   3070808,1963,1096 ,, “美国”, “IA” ,, 1,623,3,39,4日,0.375 ,,,,,,,   3070809,1963,1096 ,, “美国”, “AZ” ,, 1,4,6,65,0 ,,,,,,,,,   3070810,1963,1096 ,, “US”, “IL” ,, 1,4,6,65,3日,0.4444 ,,,,,,,

地图功能

public static class MapClass extends MapReduceBase implements Mapper<Text, Text, IntWritable, Text> {
        private int maxClaimCount = 0;
        private Text record = new Text();

        public void map(Text key, Text value, OutputCollector<IntWritable, Text> output, Reporter reporter) throws IOException {
            String claim = value.toString().split(",")[7];
            //if (!claim.isEmpty() && claim.matches("\\d")) {
            if (!claim.isEmpty()) {
                int claimCount = Integer.parseInt(claim);
                if (claimCount > maxClaimCount) {
                    maxClaimCount = claimCount;
                    record = value;
                    output.collect(new IntWritable(claimCount), value);
                }
//              output.collect(new IntWritable(claimCount), value);
            }
        }

    }

减少功能

public static class Reduce extends MapReduceBase implements Reducer<IntWritable, Text, IntWritable, Text> {

    public void reduce(IntWritable key, Iterator<Text> values, OutputCollector<IntWritable, Text> output, Reporter reporter) throws IOException {
            output.collect(key, values.next()); 
    }
}

要运行的命令:

hadoop jar ~/Desktop/wc.jar com/hadoop/patent/TopKRecords -Dmapred.map.tasks=7 ~/input  ~/output

要求:
- 根据第九列值,从数据集

中查找前K个记录(比如7)

问题:
- 由于只需要7个热门记录,我会运行7个地图任务,并确保我获得的最高记录数为maxClaimCountrecord
- 我不知道如何只收集最大记录,以便每个地图只发出一个输出

我该怎么做?

3 个答案:

答案 0 :(得分:3)

这是一个更新的答案。所有评论都不适用于它,因为它们基于原始(不正确)答案。


Mapper只应输出

output.collect(new IntWritable(claimCount), value);

没有任何比较。结果将根据索赔计数进行排序并传递给reducer。

在Reducer中使用一些优先级队列来获取前7个结果。

答案 1 :(得分:0)

您可以使用TreeMap,它以排序的方式存储密钥。 Mapper将是

public Mapper() {
   TreeMap<String, String> set = new TreeMap<String, String>();
   Void map(object key, Text value){
     Set.put("get key", value);
     If(set.size > 7) {
        Set.removeFirst()
     }

   }

Public void cleanup(){
  While(Entry<string, string> entry : map.entrySet()) {
    Conetext.write(entry.key, entry.value);
  }
}}

答案 2 :(得分:0)

您可以使用top k设计模式获取更多详细信息,请参阅以下博客 Findin Top K records in Mapreduce