MapRedcue统计文件中出现单词的次数

首先我们要知道,map阶段的map方法是读取一行就调用一次

package com.zhan.mapreduce.wordcount;

import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Counter;
import org.apache.hadoop.mapreduce.Mapper;

import java.io.IOException;

/**
 * @Classname WordCountMapper
 * @Description MrZhan
 * @Date 2021/10/7 10:42
 * @Created by 1
 */

/**
 * KEYIN:表示的是map阶段输入kv中的k类型   在默认组件下是 其实位置偏移量 LongWritable
 * VALUEIN 表示ma阶段输入kv中的v类型      在默认组件下  是一行的内容  是Test
 *          todo  MapReduce 有默认的读数据组件  叫做TextInputFormat
 *          // TODO: 2021/10/7 读数据的行为是:一行一行的读取数据
 *          k: 每一个行的起始的位置偏移量   通常没有意义
 *          v:这一行的文本内容
 * KEYOUT
 * VALUEOUT
 */
public class WordCountMapper extends Mapper<LongWritable, Text,Text,LongWritable> {

    /**
     *
     * @param key
     * @param value
     * @param context
     * @throws IOException
     * @throws InterruptedException
     *
     *
     */

    private Text outkey = new Text();
    private final static LongWritable outvalue = new LongWritable(1);
    @Override
    protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
        //todo 从程序的上下文环境中获取一个全局计数器  指定计数器所属组的名字  计数器的名字
        Counter count = context.getCounter("com.zhan", "apple_count");


        //拿去一行数据转换为String类型
        String line= value.toString();
        //根据分隔符进行切割
        String[] split = line.split("[s+]");
        //遍历数组
        for (String s : split) {
            //计数器的使用
            if ("apple".equals(s)){
                count.increment(1);
            }
            //输出数据:把每个文单词标记1   输出结果<单词,1>
            //使用上下文对象
            outkey.set(s);
            context.write(outkey,outvalue);
        }
    }
}

掌握了每个阶段的key value值就能掌握mapreduce的代码编写

package com.zhan.mapreduce.wordcount;

import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;

import java.io.IOException;

/**
 * @Classname WordCountReducer
 * @Description MrZhan
 * @Date 2021/10/7 11:03
 * @Created by 1
 */
public class WordCountReducer extends Reducer<Text, LongWritable,Text,LongWritable> {
    /**
     *
     * @param key
     * @param values
     * @param context
     * @throws IOException
     * @throws InterruptedException
     *
     * // TODO: 2021/10/7 当map的所有输出数据来到reduce之后 该如何使用reduce方法进行处理呢?
     * 1.排序  规则 根据key的字典进行排序 a-z
     * 2.分组  规则 key相同的分为一组
     * 3.分组之后,同一组的数据组成新的ke键值对,调用一次reduce方法  reduce方法基于调用的 一个分组调用一次
     * // TODO: 2021/10/7 同一组数据组成一个新的ke键值对
     *  新key:改组件共同的key
     *  新value :该组所有的value组成一个新的迭代器Iterable
     */
    private LongWritable outValue = new LongWritable();
    @Override
    protected void reduce(Text key, Iterable<LongWritable> values, Context context) throws IOException, InterruptedException {
        //统计变量
        long count = 0;
        for (LongWritable value : values) {
            //累加计算总次数
            count += value.get();
        }
        outValue.set(count);
        //最终使用上下文输出
        context.write(key,outValue);
    }
}

编写驱动类  注意,里面的args要记得设置他的输入输去路径  这里我直接在IDEA里面设置了

 

package com.zhan.mapreduce.wordcount;

/**
 * @Classname WordCountDriver
 * @Description MrZhan
 * @Date 2021/10/7 19:40
 * @Created by 1
 */

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.LongWritable;
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;

/**
 * 该类就是MapReduce程序客户端驱动类   主要是构造Job对象实例
 * 指定各种组件属性   包括 mapper  reducer类  输入输出的数据类型、输入输出的输出路径
 * 提胶job作业    job.submit()
 */
public class WordCountDriver_ve1 {
    public static void main(String[] args) throws Exception {
        //创建配置对象
        Configuration conf = new Configuration();

//        conf.set("mapreduce.framework.name","yarn");

        //构造Job作业实例 参数  (配置对象,Job名字)
        Job job = Job.getInstance(conf, WordCountDriver_ve1.class.getSimpleName());
        //设置mr程序运行的主类
        job.setJarByClass(WordCountDriver_ve1.class);

        //设置本次mr程序的mapper类型  reduce类
        job.setMapperClass(WordCountMapper.class);
        job.setReducerClass(WordCountReducer.class);

        //指定mapper阶段输出的key  value数据类型
        job.setMapOutputKeyClass(Text.class);
        job.setMapOutputValueClass(LongWritable.class);

        //指定reduce阶段输出的key  value类型  也是mr程序最终的输出数据类型
        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(LongWritable.class);

        //todo 修改reducetask个数
        job.setNumReduceTasks(1);


        //todo 设置MapReduce 程序  Combiner  慎重使用
        job.setCombinerClass(WordCountReducer.class);

        //配置本次作业的输入输出路径  和输出输出路径
        // TODO: 2021/10/7  TextInputFormat  TextOutputFormat
        Path input = new Path(args[0]);
        Path output = new Path(args[1]);
        // 配置作业的输入数据路径
        FileInputFormat.setInputPaths(job,input);
        // 配置作业的输出数据路径
        FileOutputFormat.setOutputPath(job,output);

         TODO: 2021/10/8 判断输出路径是否存在,如果存在就删除
        FileSystem fs = FileSystem.get(conf);
        if(fs.exists(output)){
            fs.delete(output,true);//rm -fr
        }
        //最终提交本次作业
        //采用waitForCompletion提交job  参数表示是否开启试试监控追踪作业的执行情况
        boolean resuultflag = job.waitForCompletion(true);

        //退出程序  和job结构进行绑定
        System.exit(resuultflag ? 0:1);

    }
}

新版的驱动类写法,推荐使用

package com.zhan.mapreduce.wordcount;

/**
 * @Classname WordCountDriver_ve2
 * @Description MrZhan
 * @Date 2021/10/7 23:16
 * @Created by 1
 */

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.conf.Configured;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.LongWritable;
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 org.apache.hadoop.util.Tool;
import org.apache.hadoop.util.ToolRunner;

/**
 * 使用工具类TooRunner提交MapReduce作业
 */
public class WordCountDriver_ve2 extends Configured implements Tool {
    public static void main(String[] args) throws Exception{
        //创建配置对象
        Configuration conf = new Configuration();
         TODO: 2021/10/8 使用工具类ToolRunner提交任务
        int status = ToolRunner.run(conf, new WordCountDriver_ve2(), args);
        //退出客户端
        System.out.println(status);
    }

    @Override
    public int run(String[] args) throws Exception {
        //构造Job作业实例 参数  (配置对象,Job名字)
        Job job = Job.getInstance(getConf(), WordCountDriver_ve2.class.getSimpleName());
        //设置mr程序运行的主类
        job.setJarByClass(WordCountDriver_ve1.class);

        //设置本次mr程序的mapper类型  reduce类
        job.setMapperClass(WordCountMapper.class);
        job.setReducerClass(WordCountReducer.class);

        //指定mapper阶段输出的key  value数据类型
        job.setMapOutputKeyClass(Text.class);
        job.setMapOutputValueClass(LongWritable.class);

        //指定reduce阶段输出的key  value类型  也是mr程序最终的输出数据类型
        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(LongWritable.class);

        //配置本次作业的输入输出路径  和输出输出路径
        // TODO: 2021/10/7  TextInputFormat  TextOutputFormat
        FileInputFormat.setInputPaths(job,new Path(args[0]));
        FileOutputFormat.setOutputPath(job,new Path(args[1]));
        //采用waitForCompletion提交job  参数表示是否开启试试监控追踪作业的执行情况
        return job.waitForCompletion(true)? 0:1;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大数据小野兽

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值