版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_31617409/article/details/69938131
一、mapper编写
package com.hadoop.mapreduce.wordcount;
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;
/**
* KEYIN 默认情况下是mr框架所读取的一行文本的起始偏移量Long,Hadoop中有自己更精简的序列化接口,不直接用Long,而是用LongWritable
* VALUEIN 默认情况下是mr框架所独到的文本的内容 String,用Text
* KEYOUT 是用户自定义逻辑处理完之后输出的数据中的key,String(单词)同上用Text
* VALUEOUT 用户逻辑处理完之后输出的数据中的value,此处是单词的次数:IntegerWritable同上;
* @author linhd
*
*/
public class WordCountMapper extends Mapper<LongWritable, Text, Text, IntWritable>{
/**
* map阶段的业务逻辑就写在自定义的map()方法中
* maptask对于每一样数据都要调用一次map方法
*/
@Override
protected void map(LongWritable key, Text value, Context context)
throws IOException, InterruptedException {
//按行切单词
String line = value.toString();
String[] words = line.split(" ");
//将单词输出为<单词,1>
for(String word:words){
//讲单词作为key,将次数1作为value,以便于后续根据单词分发,以便于相同单词回到相同的reduce task
context.write(new Text(word),new IntWritable(1));
}
}
}
二、reduce代码的编写
package com.hadoop.mapreduce.wordcount;
import java.io.IOException;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;
/**
* KEYIN VALUEIN 对应map的输出的KEYOUT,VALUEOUT
* KEYOUT VALUEOUT对应reducer输出的数据类型
* KEYOUT:单词
* VALUEOUT:总次数
* @author linhd
*
*/
public class WordCountReducer extends Reducer<Text, IntWritable, Text, IntWritable>{
/**
* <java,1><java,1><java,1><java,1><java,1>
* <hello,1><hello,1><hello,1><hello,1><hello,1>
* <banana,1><banana,1><banana,1><banana,1><banana,1>
* 入参key,是一组相同单词的keyvalue对的key,一组一组的计算,不是一个一个的计算;
*/
@Override
protected void reduce(Text key, Iterable<IntWritable> values,
Context context) throws IOException, InterruptedException {
int count=0;
// Iterator<IntWritable> iterator = values.iterator();
// while(iterator.hasNext()){
// count+=iterator.next().get();
// }
for(IntWritable value:values){
count+=value.get();
}
context.write(key, new IntWritable(count));
}
}
三、Job的编写
package com.hadoop.mapreduce.wordcount;
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;
/**
* 相当于yarn集群的客户端,yarn分配运算资源 需要在此处封装mr程序运行的相关参数,制定jar包最后提交给yarn;
*
* @author linhd
*
*/
public class WordCountDriver {
public static void main(String[] args) throws Exception {
Configuration conf = new Configuration();
Job job = Job.getInstance(conf);
//指定本程序的jar包所在的本地路径
// job.setJar("/home/linhd/...");//这种方式写死了,不好
job.setJarByClass(WordCountDriver.class);
// 告诉job要使用的mapper业务类
job.setMapperClass(WordCountMapper.class);
// 告诉job要使用的reducer业务类
job.setReducerClass(WordCountReducer.class);
// 指定mapper输出的数据的kv类型
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(IntWritable.class);
// 指定最终输出的数据的kv类型
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
// 指定job的输入原始文件所在目录
FileInputFormat.setInputPaths(job, new Path(args[0]));
// 指定job的输出结果所在的目录
FileOutputFormat.setOutputPath(job, new Path(args[1]));
//将job中配置的相关参数以及job所用的Java类所在的jar包,提交给yarn去运行
// job.submit();//这个不能了解集群运行情况
boolean result = job.waitForCompletion(true);//阻塞,查看运行情况
System.exit(result?0:1);
}
}
四、打包程序代码,打包过后会发现jar包只有几k,因为没有含有自己工程中的引用的Hadoop jar包,但是依然能够在Hadoop集群运行,因为每台机器安装的Hadoop自带jar包,可以满足依赖;
五:运行:
执行 java -cp wordcount.jar com.hadoop.mapreduce.wordcount.WordCountDriver /wordcount/input /wordcount/output命令,会发现报错,错误如下:
因为cp(classpath)中没有引用Hadoop的jar,可以将Hadoop的jar加在cp后面 但是这样过于冗长,所以可以使用Hadoop自带jar运行命令:
hadoop jar wordcount.jar com.hadoop.mapreduce.wordcount.WordCountDriver /wordcount/input /wordcount/output
得出运行结果。。