mapreduce 利用InverseMapper.class对key,value进行 交换实现词频排序

1.实现的map类                                                                                                                                                                                                                                                                     

        这个类实现 Mapper 接口中的 map 方法,输入参数中的 value 是文本文件中的一行,利用StringTokenizer 将这个字符串拆成单词,然后将输出结果org.apache.hadoop.mapred.OutputCollector 中。OutputCollector 由 Hadoop框架提供, 负责收集 Mapper 和 Reducer 的输出数据,实现 map 函数和 reduce

函数时,只需要简单地将其输出的对往 OutputCollector 中一丢即可,剩余的事框架自会帮你处理好。

代码如下:

    import java.io.IOException;  
    import java.util.StringTokenizer;  
       
    import org.apache.hadoop.io.IntWritable;  
    import org.apache.hadoop.io.LongWritable;  
    import org.apache.hadoop.io.Text;  
    import org.apache.hadoop.mapreduce.Mapper;  
      
   public class classCountWordMaper extends Mapper<LongWritable, Text, Text, IntWritable> {  
    
        @Override  
         protected void map(LongWritable key,Text value,  
                         Context context)  
                         throws IOException,InterruptedException {  
                          String text=value.toString();  
                          StringTokenizer tokens=new StringTokenizer(text);  
                          while(tokens.hasMoreTokens()){  
                                  String str=tokens.nextToken();  
                                  context.write(new Text(str), new IntWritable(1));  
                          }               
           }        
   }  

2.实现reduce类

这个类实现 Reducer 接口中的 reduce 方法, 输入参数中的 key, values 是由 Map
任务输出的中间结果,values 是一个 Iterator, 遍历这个 Iterator, 就可以得到属于同一个 key 的所有 value.
此处,key 是一个单词,value 是词频。只需要将所有的 value 相加,就可以得到这个单词的总的出现次数。

代码如下:

   import java.io.IOException;  
   import java.util.Iterator;  
      
   import org.apache.hadoop.io.IntWritable;  
   import org.apache.hadoop.io.Text;  
   import org.apache.hadoop.mapreduce.Reducer;  
    
    public class classCountWordReducer extends Reducer<Text, IntWritable, Text, IntWritable> {  
    
         @Override  
          protected void reduce(Text key,Iterable<IntWritable> values, Context context)  
                         throws IOException,InterruptedException {  
                 int total=0;  
                  Iterator<IntWritable>it=values.iterator();  
                  while(it.hasNext()){  
                         it.next();  
                          ++total;  
                  }  
                 context.write(key, new IntWritable(total));  
           }        
   }  

3.由于reduce默认的是对key进行升序排列,而我们要实现降序排列,所以就要实现一个类

import org.apache.hadoop.io.IntWritable.Comparator;
import org.apache.hadoop.io.WritableComparable;


public class IntWritableDecreasingComparator extends Comparator {

    public int compare(WritableComparable a,WritableComparable b){
        return -super.compare(a, b);
        
    }
    @Override
    public int compare(byte[] b1, int s1, int l1, byte[] b2, int s2, int l2) {
        // TODO Auto-generated method stub
        return -super.compare(b1, s1, l1, b2, s2, l2);
    }

    
}

4.主程序:

     定义了2个job,第一个job是对数据进行词频统计,并且把结果输入到临时文件当中,然后利用mapreduce的管道功能,再递交第二个job,将第一个job

的输出作为第二个排序任务的输入,注意要文件读入的格式一定要符合数据类型。第二个job通过调用系统给出的jobsort.setMapperClass(InverseMapper.class);

作为map函数,reduce利用默认IdentityReducer讲最后map输出的结果输出到输出文件当中。

代码如下:

import java.io.IOException;  
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;  
import org.apache.hadoop.io.IntWritable;  
import org.apache.hadoop.io.SequenceFile;
import org.apache.hadoop.io.Text;  


//import org.apache.hadoop.mapred.TextInputFormat;
//import org.apache.hadoop.mapred.KeyValueTextInputFormat;
import org.apache.hadoop.mapreduce.Job;  
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;  
import org.apache.hadoop.mapreduce.lib.map.InverseMapper;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;  
import org.apache.hadoop.mapreduce.lib.output.SequenceFileOutputFormat;
import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat;
import org.apache.hadoop.mapreduce.lib.input.SequenceFileInputFormat;
import org.apache.hadoop.mapreduce.lib.input.TextInputFormat;

   public class classCountWord {  
           public static void main(String[] args)throws IOException, InterruptedException, ClassNotFoundException {  
                  
                      Job job=new Job();  
                  job.setJarByClass(classCountWord.class);  
                 Path tempath=new Path(args[1]);
                 Configuration conf=new Configuration();
                  FileInputFormat.addInputPath(job,new Path(args[0])); 
                  FileSystem.get(conf).delete(tempath);
                  FileOutputFormat.setOutputPath(job,tempath);   
                  
                  job.setMapperClass(classCountWordMaper.class);  
                  job.setReducerClass(classCountWordReducer.class);  
                   
                  job.setOutputKeyClass(Text.class);  
                  job.setOutputValueClass(IntWritable.class);  
                   
                   job.setOutputFormatClass(SequenceFileOutputFormat.class);
                   job.waitForCompletion(false);
                 
                  System.out.println("开始第二个任务");
                  Job jobsort=new Job();
                  
                  FileInputFormat.addInputPath(jobsort, tempath);
                 jobsort.setOutputKeyClass(IntWritable.class);
                 jobsort.setOutputValueClass(Text.class);
                 jobsort.setInputFormatClass(SequenceFileInputFormat.class);
                 
                 jobsort.setMapperClass(InverseMapper.class);
                 jobsort.setNumReduceTasks(1);
                 Path result=new Path("/home/hadoop/result");
                 FileSystem.get(conf).delete(result);
                 FileOutputFormat.setOutputPath(jobsort, result);
                 jobsort.setSortComparatorClass(IntWritableDecreasingComparator.class);
                
                 jobsort.waitForCompletion(false);
                 
                  
           }  
   }  

注意:写程序的时候遇到的问题:

java.io.IOException: Type mismatch in key from map: expected org.apache.hadoop.io.IntWritable, recieved org.apache.hadoop.io.Text

        问题在于第二个任务读取第一个任务的输出结果的格式不对。因为默认的输出是TextOutputFormat,但是import org.apache.hadoop.mapreduce.lib.input包中没有TextInputFormat,所以出现格式不匹配的错误,后来我把第一个任务的输出格式和第二个任务读取数据的格式都设置成

job.setOutputFormatClass(SequenceFileOutputFormat.class);

jobsort.setInputFormatClass(SequenceFileInputFormat.class);

       后来程序就通了,希望大家少走弯路,能够对大家有点帮助,有问题欢迎指正~~~


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
帮我解释下面的代码:import java.io.IOException; import java.util.StringTokenizer; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.Path; import org.apache.hadoop.io.IntWritable; 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; import org.apache.hadoop.util.GenericOptionsParser; public class WordCount { public static class TokenizerMapper extends Mapper<Object, Text, Text, IntWritable>{ private final static IntWritable one = new IntWritable(1); private Text word = new Text(); public void map(Object key, Text value, Context context ) throws IOException, InterruptedException { StringTokenizer itr = new StringTokenizer(value.toString()); while (itr.hasMoreTokens()) { word.set(itr.nextToken()); context.write(word, one); } } } public static class IntSumReducer extends Reducer<Text,IntWritable,Text,IntWritable> { private IntWritable result = new IntWritable(); public void reduce(Text key, Iterable<IntWritable> values, Context context ) throws IOException, InterruptedException { int sum = 0; for (IntWritable val : values) { sum += val.get(); } result.set(sum); context.write(key, result); } } public static void main(String[] args) throws Exception { Configuration conf = new Configuration(); String[] otherArgs = new GenericOptionsParser(conf, args).getRemainingArgs(); if (otherArgs.length != 2) { System.err.println("Usage: wordcount <in> <out>"); System.exit(2); } Job job = new Job(conf, "word count"); job.setJarByClass(WordCount.class); job.setMapperClass(TokenizerMapper.class); job.setCombinerClass(IntSumReducer.class); job.setReducerClass(IntSumReducer.class); job.setOutputKeyClass(Text.class); job.setOutputValueClass(IntWritable.class); FileInputFormat.addInputPath(job, new Path(otherArgs[0])); FileOutputFormat.setOutputPath(job, new Path(otherArgs[1])); System.exit(job.waitForCompletion(true) ? 0 : 1); } }
05-31

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值