Hadoop WordCount改進實現正確識別單詞以及詞頻降序排序

來源:互聯網
上載者:User
文章目錄
  • 1.1過濾
0.參考資料:

http://radarradar.javaeye.com/blog/289257

http://blog.chinaunix.net/u3/99156/showart_2157576.html

1.思路:1.1過濾

MapReduce的第一操作就是要讀取檔案,不過我們經常會發現一個文本中會有一些我們不需要的字元,比如特殊字元。一般需要進行詞頻統計的都是單詞或者是數字,所以那些非0-9, a-z, A-Z的字元基本都是垃圾字元,我們需要進行統計,這是我們可以通過一個Regex來進行過濾,當每次多去一行文字的時候,我們將所有非0-9, a-z, A-Z的垃圾字元都替換為空白格,這樣就清楚了垃圾字元。在我們最後的詞頻統計結果中,就不會出現這些特殊字元了。

1.2降序

定義一個使用者排序比較的靜態內部類,通過這個類來控制詞頻統計最後的排序結果。我們這裡所使用的靜態內部類是IntWritableDecreasingComparator。需要注意的是必須在main函數中主動聲明使用這個比較子。

2.代碼執行個體View Code

package org.apache.hadoop.examples;import java.io.IOException;import java.util.Random;import java.util.StringTokenizer;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.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.input.SequenceFileInputFormat;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.util.GenericOptionsParser;public class WordCount2 {    public static class TokenizerMapper extends            Mapper<Object, Text, Text, IntWritable> {        private final static IntWritable one = new IntWritable(1);        private Text word = new Text();        private String pattern = "[^//w]"; // Regex,代表不是0-9, a-z, A-Z的所有其它字元,其中還有底線        public void map(Object key, Text value, Context context)                throws IOException, InterruptedException {            String line = value.toString().toLowerCase(); // 全部轉為小寫字母            line = line.replaceAll(pattern, " "); // 將非0-9, a-z, A-Z的字元替換為空白格            StringTokenizer itr = new StringTokenizer(line);            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);        }    }         private static class IntWritableDecreasingComparator extends IntWritable.Comparator {          public int compare(WritableComparable a, WritableComparable b) {            return -super.compare(a, b);          }                    public int compare(byte[] b1, int s1, int l1, byte[] b2, int s2, int l2) {              return -super.compare(b1, s1, l1, b2, s2, l2);          }      }    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);        }         Path tempDir = new Path("wordcount-temp-" + Integer.toString(                    new Random().nextInt(Integer.MAX_VALUE))); //定義一個臨時目錄                Job job = new Job(conf, "word count");        job.setJarByClass(WordCount2.class);        try{            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, tempDir);//先將詞頻統計任務的輸出結果寫到臨時目                                                         //錄中, 下一個排序任務以臨時目錄為輸入目錄。            job.setOutputFormatClass(SequenceFileOutputFormat.class);            if(job.waitForCompletion(true))            {                Job sortJob = new Job(conf, "sort");                sortJob.setJarByClass(WordCount2.class);                                FileInputFormat.addInputPath(sortJob, tempDir);                sortJob.setInputFormatClass(SequenceFileInputFormat.class);                                /*InverseMapper由hadoop庫提供,作用是實現map()之後的資料對的key和value交換*/                sortJob.setMapperClass(InverseMapper.class);                /*將 Reducer 的個數限定為1, 最終輸出的結果檔案就是一個。*/                sortJob.setNumReduceTasks(1);                 FileOutputFormat.setOutputPath(sortJob, new Path(otherArgs[1]));                                sortJob.setOutputKeyClass(IntWritable.class);                sortJob.setOutputValueClass(Text.class);                /*Hadoop 預設對 IntWritable 按升序排序,而我們需要的是按降序排列。                 * 因此我們實現了一個 IntWritableDecreasingComparator 類,                  * 並指定使用這個自訂的 Comparator 類對輸出結果中的 key (詞頻)進行排序*/                sortJob.setSortComparatorClass(IntWritableDecreasingComparator.class);                     System.exit(sortJob.waitForCompletion(true) ? 0 : 1);            }        }finally{            FileSystem.get(conf).deleteOnExit(tempDir);        }    }}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.