MapReduce实现单词计数原理及Java编程:WordCount

MapReduce实现单词计数:WordCount

单词计数的文本信息(hello.txt):

hello can i help you
i have a dream
maybe you can help me

​ 实现过程:

Map过程:并行读取文本,对读取的单词进行Map操作,每个词将会形成

​ 第一行将会形成:

​ 第二行生成

​ 第三行生成

​ Map会根据key值,自动按照ASCII值进行排序,所以,相同key值得K/V值,将会被放到一起

Reduce过程:对map的结果进行合并,计算,

​ Map将key相同得值放到了一起,所以当Reduce拿到从Map传过来得数据,可以理解为如下

< dream , 1 >

< i ,1,1 > …

​ 而Reduce进行最后得合并,就会得到如下得结果

< dream , 1 >

< i ,2 > …

​ 最后输出

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-g8x0hrTQ-1578386385884)(C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\image-20200107162331181.png)]

Java Api 编写

public class WordCountApp {

	//静态类,用于继承Mapper类,用于继承Mapper方法
    public static class MyMapper extends Mapper {//mapper的四种参数类型(源码使用了泛型,具体可以查看源码)

		//IntWritable与Text是Hadoop中的两个参数,可以简单的理解为是
		//在hadoop中的int与text格式
        private final static IntWritable one =new IntWritable(1);
        private Text word =new Text();
		
		//map操作
        public void map(Object key ,Text value ,Context context)throws IOException,InterruptedException{
            //StringTokenizer是Java.util中的类,用于将字符串切割成
            //一个字符串数组(用" "把各个字符分隔开)。
            StringTokenizer itr =new StringTokenizer(value.toString());
            //遍历文本中一行的所有字符串
            while (itr.hasMoreTokens()){
                word.set(itr.nextToken());
                //写入到map的输出文件中,这个context用于Reduce的接收
                context.write(word,one);
            }
        }
    }

//静态类,用于继承Reduce类,编写Reduce方法
    public static class MyReduce extends Reducer{
		//统计计数,即记录单词的出现次数,最后输出的辅助类
        private final static IntWritable result =new IntWritable();

		//reduce操作
        public void reduce(Text key , Iterable values, Context context)throws IOException,InterruptedException{
            //记录单词的出现个数,因为在Reduce中没有int类型,所以要
            //用IntWritable进行包装
            
            int sum=0;
            //上面讲到,Reduce拿到Map的值的形式,这个Reduce会执行在每
            //一个块中,用于计数,所以每一个单词都是从0开始计数
            for (IntWritable val : values){
                sum +=val.get();
            }
            //int sum包装进 IntWritable
            result.set(sum);
            //写入到最终会输出的地方
            context.write(key,result);
        }
    }
    
    //主方法
    public static void main(String[] args) throws IOException, URISyntaxException, ClassNotFoundException, InterruptedException {
        //本此编码是在Windowx编程,所以要加Hdfs的路径
        String INPUT_PATH="hdfs://10.30.60.3:8020/a";
        String OUTPUT_PATH="hdfs://10.30.60.3:8020/b";

        Configuration configuration =new Configuration();
        final FileSystem fileSystem=FileSystem.get(new URI(INPUT_PATH),configuration);

		//确保INPUT的路径存在,而OutPut得路径会在最后生成结果时生成、
		//所以确保OUTPUT得文件不存在
        if(fileSystem.exists(new Path(OUTPUT_PATH))){
            fileSystem.delete(new Path(OUTPUT_PATH),true);
        }

		//设置job
        Job job =Job.getInstance(configuration,"WordCountApp");
		
		//设置主类
        job.setJarByClass(WordCountApp.class);

        //设置mapper
        job.setMapperClass(MyMapper.class);
        //设置Mapper的输出格式
        job.setMapOutputKeyClass(Text.class);
        job.setMapOutputValueClass(IntWritable.class);

        //设置Reduce
        job.setReducerClass(MyReduce.class);
        //设置Reduce格式
        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(IntWritable.class);

        //设置输入格式
        job.setInputFormatClass(TextInputFormat.class);
        Path inputPath=new Path(INPUT_PATH);
        FileInputFormat.addInputPath(job,inputPath);

        //设置输出格式
        job.setOutputValueClass(TextOutputFormat.class);
        Path outputPath=new Path(OUTPUT_PATH);
        FileOutputFormat.setOutputPath(job,outputPath);

        //提交
        System.exit(job.waitForCompletion(true)? 0:1);
    }
}

你可能感兴趣的:(大数据,java,Linux)