不是井里没有水,而是你挖的不够深。不是成功来得慢,而是你努力的不够多。
昨天我们用Hadoop
自带的WordCount.class
统计了一个文件每个单词出现了几次。
今天我们自己写MapReduce
。
第一步:写Map类
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.apache.hadoop.yarn.webapp.hamlet.Hamlet;
import java.io.IOException;
/**
* map程序逐行读取数据,将每一行数据的起始偏移量作为key,类型是LongWritable,
* 将每一行数据的内容作为value(Text),传给我们写的map,
* 经过map阶段的处理,输出的key是Text,value是IntWritable。
*
* 调用机制::
* 1,谁在调用:map在调用
* 2,怎么调:是在当前mapreduce过程中,每读取一行数据,调用一次map
*/
public class CountMap extends Mapper<LongWritable, Text, Text, IntWritable> {
@Override
protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
//key:读进来时,数据的偏移量,一般没什么用
//value:具体读进来的数据 hello
String word = value.toString();
String[] split = word.split(" ");
for (String w:split) {
//(hello ,1)(as ,1)(hello,1)
context.write(new Text(w),new IntWritable(1));
}
}
}
第二步:写Reduce类
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;
import java.io.IOException;
/**
* 在map中每次只用相同的才会过来
* (hello,1) (hello,1) (hello,1) (hello,1)........
* 他会自己改写成(hello,(1,1,1,1,1,1....))
*
* reduce的调用机制
* 1,谁在调用:reduce阶段在调用
* 2,怎么调用:reduce每收到一组key相同的数据,调用一次
*/
public class CountReduce extends Reducer<Text, IntWritable,Text,IntWritable> {
//重写Reduce方法
@Override
protected void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {
Integer count = 0;
for (IntWritable v:values){
count++;
}
context.write(key, new IntWritable(count));
}
}
第三步:实现类
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.input.TextInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat;
import java.io.IOException;
public class CountDriver {
public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
Configuration conf = new Configuration();
conf.set("yarn.resorcemanager.hostname","192.168.72.110");
conf.set("fs.deafutFS","hdfs://192.168.72.110:9000/");
Job job = Job.getInstance(conf);
job.setJarByClass(CountDriver.class);
//设置本次job是使用map,reduce
job.setMapperClass(CountMap.class);
job.setReducerClass(CountReadius.class);
//设置本次map和reduce的输出类
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(IntWritable.class);
job.setOutputKeyClass(Text.class);
job.setOutputKeyClass(IntWritable.class);
//制定本次job读取源数据时需要用到的组件:我们的源文件在hdfs的文本文件中,用TextInputFormat
job.setInputFormatClass(TextInputFormat.class);
//制定本次job输出数据需要的组件:我们要输出到hdfs文件中,用TextOutputFormat
job.setOutputFormatClass(TextOutputFormat.class);
//设置输入路径
FileInputFormat.setInputPaths(job,new Path(args[0]));
FileOutputFormat.setOutputPath(job,new Path(args[1]));
//提交任务,客户端返回
job.submit();
//核心代码:提交jar程序给yarn,客户端不退出,等待接收mapreduce的进度信息,
//打印进度信息,并等待最终运行的结果
//客户端true的含义:等着
//result:返回true则跑完了,false,出错了
boolean resule = job.waitForCompletion(true);
System.exit(resule ? 0 : 1);
}
}
写完主类,我们要打jar
包。本人是idea
。
这是打包的网址。
https://blog.csdn.net/njxiaoxiao79/article/details/85679992
打包完后,将打包完的jar包上传到虚拟机。
[root@Tyler01 home]# rz
打开hadoop集群
[root@Tyler01 home]# start-all.sh
执行hadoop命令
[root@Tyler01 home]# hadoop jar a22.jar /wc/word.txt /wc/output
查看结果
hadoop fs -cat /wc/out/part-r-00000
as 3
daniu 2
hello 10
kopmgkomg 1
pp 2
tyler 1
tylerhjghjghjghjgjh 1