1、需求
在给定的文本文件中统计输出每一个单词出现的总次数。
2、环境准备
(1)创建Maven工程
(2)在pom.xml文件中添加如下依赖
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>RELEASE</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.8.2</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-common</artifactId>
<version>2.7.2</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>2.7.2</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-hdfs</artifactId>
<version>2.7.2</version>
</dependency>
</dependencies>
(2)在项目的src/main/resources目录下,新建一个文件,命名为“log4j.properties”,在文件中填入
log4j.rootLogger=DEBUG,myConsole
log4j.appender.myConsole=org.apache.log4j.ConsoleAppender
log4j.appender.myConsole.Target=System.out
log4j.appender.myConsole.layout=org.apache.log4j.PatternLayout
log4j.appender.myConsole.layout.ConversionPattern=[%-5p] %d(%r) --> [%t] %l: %m %x %n
3.编写程序
(1)编写Mapper类
import java.io.IOException;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;
/** 进行数据的映射,形如(word,1)的形式
* @author yqw
* @since 2020-07-25 22:30
*/
/*因为数据要进行网络传输,所以要将java的数据类型转换为hadoop的,例如long->LongWritable,String->Text
LongWritable 每一行输入数据的起始偏移量
Text 每一行输入数据的类型
Text 输出数据key的类型
IntWritable 输出数据value的值
*/
public class WordCountMapper extends Mapper<LongWritable, Text, Text, IntWritable>{
// 创建一个对象,供map提交key使用
Text k = new Text();
// 输出数据的value,一般都为1
// 此处的IntWritable是hadoop中的数据类型,相当于java中的int
IntWritable v = new IntWritable(1);
/**
* 每调用一次map就会读取一行数据
* @param key 输入数据的偏移量
* @param value 输入数据
* @param context 用于暂时存储 map() 处理后的结果
* @throws IOException
* @throws InterruptedException
*/
@Override
protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
// 1 获取一行
String line = value.toString();
// 2 切割
String[] words = line.split(" ");
// 3 输出
for (String word : words) {
// 把java中的值转换为hadoop类型的
k.set(word);
// 提交给context,它会调用框架执行combine、shuffle、sort等操作
context.write(k, v);
}
}
}
(2)、编写Reducer类
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;
import java.io.IOException;
/**
* @author yqw
* @since 2020-07-25 22:30
*/
/*
Text map输出数据的key
IntWritable map输出数据的value
Text reduce输出数据key的类型
IntWritable reduce输出数据value的值
*/
public class WordCountRuducer extends Reducer<Text, IntWritable, Text, IntWritable> {
int sum;
IntWritable v = new IntWritable();
/**
*
* @param key mapper传入过来的key
* @param values mapper传入过来的values,框架对它进行自动的combine、shuffle、sort,结果形如(1,1,1,2,2,3…….),
* @param context
* @throws IOException
* @throws InterruptedException
*/
@Override
protected void reduce(Text key, Iterable<IntWritable> values,Context context) throws IOException, InterruptedException {
// 1 累加求和
sum = 0;
for (IntWritable count : values) {
sum += count.get();// count.get()是获取count的int类型的值
}
// 2 输出
v.set(sum);
context.write(key,v);
}
}
(3)、编写Driver驱动类
package com.atguigu.hdfs;
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.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import java.io.IOException;
/**
* @author yqw
* @since 2020-07-25 22:31
*/
public class WordCountDriver {
public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
// 1 获取配置信息以及封装任务
Configuration configuration = new Configuration();
// 每个MapReduce任务都被初始化为一个Job,它分为两个阶段,map和reduce阶段
Job job = Job.getInstance(configuration);
// 2 设置jar加载路径
job.setJarByClass(WordCountDriver.class);
// 3 设置map和reduce类
job.setMapperClass(WordCountMapper.class);
job.setReducerClass(WordCountRuducer.class);
// 4 设置map输出
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(IntWritable.class);
// 5 设置最终输出kv类型
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
// 6 设置输入和输出路径
FileInputFormat.setInputPaths(job, new Path(args[0]));
FileOutputFormat.setOutputPath(job, new Path(args[1]));
// 7 提交
boolean result = job.waitForCompletion(true);
// 8 退出程序
System.exit(result ? 0 : 1);
}
}
4.本地测试
我的输入文件为word.txt
输出结果:
好了,如何用java实现自定义MarpReduce中的WordCount就讲到这了,要是有什么错误,欢迎各位指出!