需要定义三个类,jobMain类,Mapper类,Reducer类
jobMain类
这个类负责整体的协调运行
package com.legendlee.wordCount;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.conf.Configured;
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.TextInputFormat;
import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat;
import org.apache.hadoop.util.Tool;
import org.apache.hadoop.util.ToolRunner;
public class jobMain extends Configured implements Tool {
@Override
public int run(String[] args) throws Exception {
//获取到job对象,用于任务的组织
Job job = Job.getInstance(this.getConf(), "legendlee");
//如果导成jar包在虚拟机上运行需要加上,若不加则会报错。如果在本地运行,则不需要加这行代码
job.setJarByClass(jobMain.class );
//第一步,读取文件,解析成key value对,k1,v1
job.setInputFormatClass(TextInputFormat.class);
//路径
TextInputFormat.addInputPath(job, new Path("hdfs://192.168.109.100:8020/wordCount"));
//第二步:自定义map逻辑,接收第一步的k1,v1,转换成新的k2,v2进行输出
job.setMapperClass(wordCountMapper.class);
//设置k2,v2类型
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(IntWritable.class);
/**
* 第三到第六步都省掉
* 3.分区 相同key的value发送到同一个reduce里面去
* 4.排序
* 5.规约
* 6.分组
*/
//第七步,设置reducer类,接收k2,v2,输出k3,v3
job.setReducerClass(wordCountReducer.class);
//设置k3输出的类型
job.setOutputKeyClass(Text.class);
//设置v3输出类型
job.setOutputValueClass(IntWritable.class);
//第八步:设置输出类
job.setOutputFormatClass(TextOutputFormat.class);
TextOutputFormat.setOutputPath(job, new Path("hdfs://192.168.109.100:8020/wordCountOut2"));
//提交任务
boolean b = job.waitForCompletion(true);
return b?0:1;
}
public static void main (String[]args) throws Exception {
Configuration configuration = new Configuration();
//任务完成之后,返回一个状态码值,如果状态码值是0,则表示程序运行成功
int run = ToolRunner.run(configuration, new jobMain(), args);
System.exit(run);
}
}
Mapper类
map的逻辑处理类
package com.legendlee.wordCount;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;
import org.testng.annotations.Test;
import java.io.IOException;
/**
* 继承Mapper表示是一个Mapper类,需要四个泛型
* k1 v1 k2 v2
* */
@Test
public class wordCountMapper extends Mapper<LongWritable,Text,Text,IntWritable>{
Text text=new Text();
IntWritable writable=new IntWritable();
/**覆写父类的map方法 每一行数据都要掉用map方法 我们的处理逻辑都写在map方法里面
*
* hdfs的最原始的数据:
* hello,world,hadoop
hive,sqoop,flume,hello
kitty,tom,jerry,world
hadoop
经过TextInputFormat之后
0 hello,world,hadoop
18 hive,sqoop,flume,hello
40 kitty,tom,jerry,world
61 hadoop
*
*
* key k1 行偏移量
* value 行文本内容 需要切割 转换成新的文本输出
* context 上下文
*
* */
@Override
protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
// super.map(key, value, context);
/**
hello,world,hadoop
hive,sqoop,flume,hello
kitty,tom,jerry,world
hadoop
*/
String line =value.toString();
//把数据切割成一个个单词
String[] split = line.split(",");
//遍历
for (String word : split) {
text.set(word);
writable.set(1);
context.write(text,writable);
}
}
}
Reduce类
Reduce的逻辑处理类
package com.legendlee.wordCount;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;
import java.io.IOException;
public class wordCountReducer extends Reducer<Text,IntWritable,Text,IntWritable> {
/**
*覆写Reduce方法
* @param key k2
* @param values 是一个集合,集合里面的数据类型是v2
* @param context 上下文对象,将我们的数据往外写
* @throws IOException
* @throws InterruptedException
*/
@Override
protected void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {
// super.reduce(key, values, context);
/**
hello,world,hadoop
hive,sqoop,flume,hello
kitty,tom,jerry,world
hadoop
k2:v2
hello<1,1>
world<1,1>
hadoop<1,1>
.
*/
int a=0;
//values表示元素个数的一个集合
//value是 每一个1
for (IntWritable value : values) {
//i表示获得集合中的每一个元素
int i=value.get();
a+=i;
}
//将我们的数据写出去
context.write(key,new IntWritable(a));
}
}
程序运行的最后结果
如图: