Hadoop-Mapreduce-英文单词计数

  1 package mapred;
  2 
  3 import java.io.IOException;
  4 import java.util.StringTokenizer;
  5 import org.apache.hadoop.conf.Configuration;
  6 
  7 import org.apache.hadoop.fs.Path;
  8 import org.apache.hadoop.io.IntWritable;
  9 import org.apache.hadoop.io.Text;
 10 import org.apache.hadoop.io.WritableComparable;
 11 import org.apache.hadoop.mapreduce.Job;
 12 import org.apache.hadoop.mapreduce.Mapper;
 13 
 14 import org.apache.hadoop.mapreduce.Reducer;
 15 import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
 16 import org.apache.hadoop.mapreduce.lib.input.SequenceFileInputFormat;
 17 
 18 import org.apache.hadoop.mapreduce.lib.map.InverseMapper;
 19 import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
 20 import org.apache.hadoop.mapreduce.lib.output.SequenceFileOutputFormat;
 21 import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat;
 22 
 23 public class WordCount {
 24 
 25     // 自定义Mapper静态内部Class 继承父类 Mapper类,进一步实现map过程
 26     public static class TokenizerMapper extends
 27             Mapper<Object, Text, Text, IntWritable> {
 28         public void map(Object key, Text value, Context context)
 29                 throws IOException, InterruptedException {
 30             System.out.println(key);
 31             // Key
 32             Text keyOut;
 33             // 定义整数1, 每个单词计数一次
 34             IntWritable valueOut = new IntWritable(1);
 35 
 36             // 构造一个用来解析输入value值的StringTokenizer对象
 37             StringTokenizer token = new StringTokenizer(value.toString());
 38             while (token.hasMoreTokens()) {
 39                 // 返回从当前位置到下一个分割符的字符串
 40                 keyOut = new Text(token.nextToken());
 41                 // map过程输出键值对:输出每个被拆分出来的单词,以及计数1
 42                 context.write(keyOut, valueOut);
 43             }
 44         }
 45     }
 46 
 47     // 自定义Reducer Class 继承父类 Reducer类,进一步实现reduce过程
 48     public static class IntSumReducer extends
 49             Reducer<Text, IntWritable, Text, IntWritable> {
 50         private IntWritable result = new IntWritable();
 51 
 52         public void reduce(Text key, Iterable<IntWritable> values,
 53                            Context context) throws IOException, InterruptedException {
 54             int sum = 0;
 55             for (IntWritable val : values) {
 56                 sum += val.get();
 57             }
 58             result.set(sum);
 59             context.write(key, result);
 60         }
 61     }
 62 
 63     // 自定义实现降序
 64     // Hadoop默认对IntWritable按升序排序,重写IntWritable.Comparator类实现降序
 65     private static class IntWritableDecreaseingComparator extends IntWritable.Comparator {
 66         @Override
 67         public int compare(WritableComparable a, WritableComparable b) {
 68             return -super.compare(a, b);// 比较结果取负数即可降序
 69         }
 70         @Override
 71         public int compare(byte[] b1, int s1, int l1, byte[] b2, int s2, int l2) {
 72             return -super.compare(b1, s1, l1, b2, s2, l2);
 73         }
 74     }
 75 
 76     // 入口
 77     public static void main(String[] args) throws Exception {
 78         // 任何作用的配置信息必须通过Configuration传递,通过Configuration可以实现在多个mapper和多个reducer任务之间共享信息
 79         Configuration conf = new Configuration();
 80 
 81         // 定义一个临时目录:hdfs://localhost:9000/wordcount1 是hdfs上不存在的目录(hdfs://localhost:9000/肯定存在)
 82         // 自定义一个临时目录,如果目录存在请先删除目录后,再运行
 83         Path tempDir = new Path("hdfs://localhost:9000/wordcount1");
 84 
 85         try {
 86             // 创建作业 job
 87             Job job = Job.getInstance(conf, "word count ");
 88 
 89             //  通过传入的WordCount类Class 设置job的jar包
 90             job.setJarByClass(WordCount.class);
 91 
 92             //  设置Mapper类Class
 93             job.setMapperClass(TokenizerMapper.class);
 94             //  设置Combine类Class
 95             job.setCombinerClass(IntSumReducer.class);
 96             //  设置Reducer类Class
 97             job.setReducerClass(IntSumReducer.class);
 98 
 99             // 自定义分区
100             job.setNumReduceTasks(2);
101 
102             // 指定输出类型
103             job.setOutputKeyClass(Text.class);//  设置输出Key类Class
104             job.setOutputValueClass(IntWritable.class);//  设置输出Value类Class
105 
106             // 指定统计作业输出格式,和排序作业的输入格式应对应
107             job.setOutputFormatClass(SequenceFileOutputFormat.class);
108 
109             // 指定待统计文件目录
110             FileInputFormat.addInputPath(job, new Path("hdfs://localhost:9000/words"));
111 
112             // 先将词频统计作业的输出结果写到临时目录中,下一个排序作业以临时目录为输入目录
113             FileOutputFormat.setOutputPath(job, tempDir);
114 
115             // 提交job
116             // waitForCompletion提交作业后,每秒会轮询作业进度,如果发现和上次报告后有改变,就把进度报告到控制台,
117             // 作业完成后,如果成功就显示作业计数
118             boolean result = job.waitForCompletion(true);
119             if (result) {
120                 // 创建作业 sortJob
121                 Job sortJob = Job.getInstance(conf, "sort");
122                 sortJob.setJarByClass(WordCount.class);
123 
124                 // 指定临时目录作为排序作业的输入
125                 FileInputFormat.addInputPath(sortJob, tempDir);
126 
127                 // Hadoop 默认的是TextInputFormat和TextOutputFormat,此处可以显示地配置
128                 sortJob.setInputFormatClass(SequenceFileInputFormat.class);
129 
130                 // 由Hadoop库提供,作用是实现map()后的数据对key和value交换
131                 sortJob.setMapperClass(InverseMapper.class);
132 
133                 // 将Reducer的个数限定为1,最终输出的结果文件就是一个
134                 sortJob.setNumReduceTasks(1);
135 
136                 // 最终输出目录,如果目录存在请先删除目录后,再运行
137                 FileOutputFormat.setOutputPath(sortJob, new Path("hdfs://localhost:9000/wordcount2"));
138 
139                 //  设置输出Key类Class
140                 sortJob.setOutputKeyClass(IntWritable.class);
141                 //  设置输出Value类Class
142                 sortJob.setOutputValueClass(Text.class);
143                 // 一般情况下,mapper和reducer输出的数据类型是一样的,所以可以用上面两条命令;
144                 // 如果不一样,可以用下面两条命令单独指定mapper输出的key、value数据类型
145                 // job.setMapOutputKeyClass(Text.class);
146                 // job.setMapOutputValueClass(IntWritable.class);
147 
148                 sortJob.setOutputFormatClass(TextOutputFormat.class);
149                 // Hadoop 默认的是TextInputFormat和TextOutputFormat,此处可以显示地配置
150                 // job.setInputFormatClass(TextInputFormat.class);
151                 // job.setOutputFormatClass(TextOutputFormat.class);
152 
153                 // Hadoop默认对IntWritable按升序排序,重写IntWritable.Comparator类实现降序
154                 sortJob.setSortComparatorClass(IntWritableDecreaseingComparator.class);
155 
156                 // 提交sortJob
157                 // waitForCompletion提交作业后,每秒会轮询作业进度,如果发现和上次报告后有改变,就把进度报告到控制台,
158                 // 作业完成后,如果成功就显示作业计数
159                 boolean result2 = sortJob.waitForCompletion(true);
160                 if (result2) {
161                     System.out.println("***********ok************");
162                 }
163             }
164         } catch (Exception ex) {
165             ex.printStackTrace();
166         }
167     }
168 }
169 
170 // 查看指定路径文件
171 // hadoop fs -ls hdfs://localhost:9000/
172 // 返回结果,如下:
173 //Found 5 items
174 //-rw-r--r--   3 jiangshan supergroup  573545760 2021-09-08 15:48 hdfs://localhost:9000/SBSNTEST111.txt
175 //-rw-r--r--   3 jiangshan supergroup         28 2021-09-08 16:01 hdfs://localhost:9000/testcreate
176 //drwxr-xr-x   - jiangshan supergroup          0 2021-09-08 19:39 hdfs://localhost:9000/wordcount1
177 //drwxr-xr-x   - jiangshan supergroup          0 2021-09-08 19:39 hdfs://localhost:9000/wordcount2
178 //-rw-r--r--   3 jiangshan supergroup  163254798 2021-09-08 16:56 hdfs://localhost:9000/words
179 
180 // 查看指定路径文件
181 // hadoop fs -ls hdfs://localhost:9000/wordcount1
182 // 返回结果,如下:
183 //Found 3 items
184 //-rw-r--r--   3 jiangshan supergroup          0 2021-09-08 19:54 hdfs://localhost:9000/wordcount1/_SUCCESS
185 //-rw-r--r--   3 jiangshan supergroup      27888 2021-09-08 19:54 hdfs://localhost:9000/wordcount1/part-r-00000
186 //-rw-r--r--   3 jiangshan supergroup      27364 2021-09-08 19:54 hdfs://localhost:9000/wordcount1/part-r-00001
187 
188 // 查看指定路径文件
189 // hadoop fs -ls hdfs://localhost:9000/wordcount2
190 // 返回结果,如下:
191 //Found 2 items
192 //-rw-r--r--   3 jiangshan supergroup          0 2021-09-08 19:54 hdfs://localhost:9000/wordcount2/_SUCCESS
193 //-rw-r--r--   3 jiangshan supergroup      36850 2021-09-08 19:54 hdfs://localhost:9000/wordcount2/part-r-00000
194 
195 // 将路径指定文件的内容输出到stdout
196 // hadoop fs -cat hdfs://localhost:9000/testcreate
197 // 返回结果,文本文件内容
198 // Hello Hadoop 888@Chinasofti
个人学习记录
原文地址:https://www.cnblogs.com/jeshy/p/15244712.html