一、概述
这是一个基于Hadoop MapReduce框架实现的经典词频统计程序。程序会统计输入文本中每个单词出现的次数,并将结果输出到HDFS文件系统。
二、代码结构
package com.bigdata.wc;
// Hadoop核心类库导入
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
// 数据类型定义
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
// MapReduce框架类
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;
import java.io.IOException;
import java.util.StringTokenizer;
三、核心组件解析
1. Mapper组件(TokenizerMapper)
public static class TokenizerMapper
extends Mapper<Object, Text, Text, IntWritable> {
// 定义常量1(避免重复创建对象)
private final IntWritable one = new IntWritable(1);
private final Text word = new Text();
@Override
protected void map(Object key, Text value, Context context)
throws IOException, InterruptedException {
// 将文本行转换为字符串
String line = value.toString();
// 使用字符串分割器(默认按空格分割)
StringTokenizer tokenizer = new StringTokenizer(line);
// 遍历所有单词
while (tokenizer.hasMoreTokens()) {
// 设置单词到Text对象
word.set(tokenizer.nextToken());
// 输出键值对 <单词, 1>
context.write(word, one);
}
}
}
输入输出说明:
- 输入:
<行偏移量, 文本行内容>
- 输出:
<单词, 1>
2. Reducer组件(SumReducer)
public static class SumReducer
extends Reducer<Text, IntWritable, Text, IntWritable> {
@Override
protected void reduce(Text key, Iterable<IntWritable> values, Context context)
throws IOException, InterruptedException {
int sum = 0;
// 累加所有相同单词的计数值
for (IntWritable val : values) {
sum += val.get();
}
// 输出最终结果 <单词, 总次数>
context.write(key, new IntWritable(sum));
}
}
处理流程:
- 接收来自Map阶段的分组数据(相同单词的计数值集合)
- 对每个单词的所有计数值求和
- 输出最终统计结果
3. 主程序(Main方法)
public static void main(String[] args) throws Exception {
// 设置Hadoop用户和本地库路径
System.setProperty("HADOOP_USER_NAME", "root");
System.setProperty("hadoop.home.dir", "A:\\hadoop");
// 创建配置对象
Configuration conf = new Configuration();
// 配置HDFS和YARN参数
conf.set("fs.defaultFS", "hdfs://bigdata01:9000"); // HDFS地址
conf.set("yarn.resourcemanager.address", "bigdata01:8032"); // YARN资源管理器地址
conf.set("mapreduce.app-submission.cross-platform", "true"); // 跨平台提交
conf.set("mapred.jar", "指定JAR包路径"); // 作业JAR包路径
// 解析命令行参数
args = new GenericOptionsParser(conf, args).getRemainingArgs();
if (args.length < 2) {
System.err.println("Usage: wordcount <input> <output>");
System.exit(2);
}
// 创建作业实例
Job job = Job.getInstance(conf, "wordcount");
job.setJarByClass(WordCount.class);
// 设置Mapper和Reducer
job.setMapperClass(TokenizerMapper.class);
job.setReducerClass(SumReducer.class);
// 设置Combiner(使用Reducer逻辑进行本地聚合)
job.setCombinerClass(SumReducer.class);
// 指定输入输出路径
FileInputFormat.addInputPath(job, new Path(args[0]));
FileOutputFormat.setOutputPath(job, new Path(args[1]));
// 提交作业并等待完成
System.exit(job.waitForCompletion(true) ? 0 : 1);
}
四、关键配置说明
配置项 | 说明 | 推荐值 |
---|---|---|
fs.defaultFS | HDFS默认地址 | hdfs://namenode:9000 |
mapreduce.framework.name | 运行框架 | yarn |
mapreduce.job.jar | 作业JAR包路径 | 绝对路径 |
五、运行流程
- 数据输入:
hdfs dfs -put localfile /input
- 提交作业:
hadoop jar WordCount.jar com.bigdata.wc.WordCount /input /output
- 查看结果:
hdfs dfs -cat /output/part-r-00000
六、注意事项
- 路径规范:
- 避免中文路径和空格
- 推荐使用绝对路径
- 权限管理:
hdfs dfs -chmod -R 777 /tmp
- 常见问题处理:
- 输出目录已存在:添加自动删除逻辑
- 内存不足:增加配置参数
conf.set("mapreduce.map.memory.mb", "1024");
conf.set("mapreduce.reduce.memory.mb", "1024");