一、环境准备
搭建mapreduce开发环境
(1)分别配置mapred-site.xml、yarn-site.xml和slaves文件,并分发给slave1,slave2,之前配过文件,就不在这详细说明了。
(2)初始化
(3)start
(4)8088端口页面
二、实验分析
开发mapreduce程序(Map,reduce和driver),统计wordcount.txt文件中的单词的数量。
三、实验实现与结果
(1)实现代码
package org.example;
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 java.io.IOException;
import java.util.StringTokenizer;
public class WordCount {
/**
* 静态内容部类
* 规定 map 中用到的数据类型,这里的 Text 相当于 jdk 中的 String IntWritable 相当于 jdk 的 int 类型,* 这样做的原因主要是为了 hadoop 的数据序化而做的。
*/
public static class TokenizerMapper
extends Mapper<Object, Text, Text, IntWritable> {
// 为了防止每次调用 map 方法,都会创建对象,将 one 和 word 提取出来
// 声时一个 IntWritable 变量,作计数用,每出现一个 key,给其一个 value=1 的值
private final static IntWritable one = new IntWritable(1);
// 用来暂存 map 输出中的 key 值,Text 类型的
private Text word = new Text();
/**
* map 的作用就是拆分,简单来说就是将单词打散,计数
* 它是和 Mapper 类中的相对应的,此处的 Object key,Text value 的类型和上边的 Object, * Text 是相对应的,而且最好一样,不然的话,多数情况运行时会报错。
*
* @param key
1 / 12
* @param value
* @param context * @throws IOException
* @throws InterruptedException
*/
public void map(Object key, Text value, Context context
) throws IOException, InterruptedException {
/**** map 端业务代码****/
//Hadoop 读入的 value 是以行为单位的,其 key 为该行所对应的行号,因为我们要计算每个单词的数目,//默认以空格作为间隔,故用 StringTokenizer 辅助做字符串的拆分,也可以用 string.split("")来作。
StringTokenizer itr = new StringTokenizer(value.toString());
//遍历一下每行字符串中的单词
while (itr.hasMoreTokens()) {
//出现一个单词就给它设成一个 key 并将其值设为 1
word.set(itr.nextToken());
context.write(word, one); //输出设成的 key/value 值
}
}
}
/**
* reduce 的静态类,这里和 Map 中的作用是一样的,设定输入/输出的值的类型
*/
public static class IntSumReducer
extends Reducer<Text, IntWritable, Text, IntWritable> {
private IntWritable result = new IntWritable();
/**
* reduce 的作用就是合并
*
* @param key
* @param values * @param context * @throws IOException
* @throws InterruptedException
*/
public void reduce(Text key, Iterable<IntWritable> values, Context context
) throws IOException, InterruptedException {
/****reduce 端业务代码****/
int sum = 0;
// 遍历数据,进行统计
for (IntWritable val : values) {
//由于 map 的打散,这里会得到如,{key,values}={"hello",{1,1,....}},这样的集合
sum += val.get();
}
// 单词出现频率总和,并设成 result 对应的值
result.set(sum);
//此时的 key 即为 map 打散之后输出的 key,没有变化,变化的时 result,以前得到的是一个数字的集合,//已经给算出和了,并做为 key/value 输出。
context.write(key, result);
}
}
public static void main(String[] args) throws Exception {
// 创建配置文件,取得系统的参数
Configuration conf = new Configuration();
// 创建一个 job,应用封装任务,把 job 提交到集群
Job job = Job.getInstance(conf, "word count");
/**** 对 job 任务封装(反射,文件输入,输出)****/
// job 要执行 MyWordCount.class 这个字节码文件
job.setJarByClass(WordCount.class);
// map 端字节码
job.setMapperClass(TokenizerMapper.class);
job.setCombinerClass(IntSumReducer.class);
// reduce 端字节码
job.setReducerClass(IntSumReducer.class);
// reduce 端输出的 key,value 字节码
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
// map 端输入文件路径,初始化要计算 word 的文件的路径
FileInputFormat.addInputPath(job, new Path("E:\\wordcount.txt"));
// reduce 端输出文件路径
FileOutputFormat.setOutputPath(job, new Path("E:\\output"));
// 提交任务
// waitForCompletion 设置 verbose 值为 true,可以打印对应进度
// system.exit(int status) status 为 0 时为正常退出程序,也就是结束当前正在运行中的 java 虚拟机// status 为非 0 的其他整数(包括负数,一般是 1 或者-1),表示非正常退出当前程序。
System.exit(job.waitForCompletion(true) ? 0 : 1);
}
}
(2)idea运行
(3)
运行上述词频统计代码,执行结果如下
(4)单词数量