WordCount程序

WordCount程序

  • 目的是统计每个单词出现的次数
a b c c
b e a 
c e a
  • 将上述转换成
a 3
b 2
c 3
e 2

步骤

  • Mapper
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 java.io.IOException;

//map阶段

/**
 * map类要继承Mapper
 * <KEYIN, VALUEIN, KEYOUT, VALUEOUT>
 * 先是读取一行,即数据的缩进是keyin,数据是valuein
 * KEYIN : 表示Map阶段数据输入的时候的数据类型,在默认的数据读取组件,叫InputFormat,他是一行一行的读取待处理的数据
 * 读取一行返回一行给mr程序,这种情况下,keyin就表示每一行的起始偏移量(首行缩进)  他的数据类型是Long
 * <p>
 * VALUEIN: 表示Map阶段数据输入的时候value的数据类型,在默认的读取组件下,valuein就表示读取的这一行内容 因此数据类型是String
 * <p>
 * KEYOUT: 表示Map阶段数据输出的key的数据类型  在本案例1中 输出的key是单词  因此数据类型是String
 * <p>
 * VALUEOUT: 表示Map阶段数据输出的类型 在本案例中 value输出的是数字 因此数据类型是int
 * <p>
 * String int...是jdk自带的·数据类型 在序列化的时候效率低下  因此hadoop封装了数据类型 即writable结尾的
 */
public class WordCountMapper extends Mapper<LongWritable, Text, Text, IntWritable> {
    /**
     * 这里就是Mapper阶段具体的业务逻辑实现方法,该方法的调用取决于读取数据的组件有没有给mr传入数据
     * 如果有的话,每传入一个<k,v>对 就会被调用一次(这个kv对就是代表一行内容)
     * (一个个kv对连续传入,直到没有)
     *
     * @param key
     * @param value
     * @param context
     * @throws IOException
     * @throws InterruptedException
     */
    @Override
    protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {

        //拿到传入进来的内容,把数据类型转换为String
        String line = value.toString();//valuein中的一行

        //将这一行内容按照分隔符进行一行内容的切割,切割成一个个的单词
        String[] words = line.split(" ");

        //遍历数组,没出现一个单词 就标记一个数字1<单词,1>
        for (String word : words) {
            //使用mr程序的上下文,把mapper阶段处理的数据发送给reduce,让其接收
            context.write(new Text(word), 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;

/**
 * 继承Reducer
 * 这里是mr程序  reducer阶段
 * KEYIN : 就是reducer阶段输入的数据类型 也是map的key的输出  在本案例中就是单词
 * <p>
 * VALUEIN : 就是reducer阶段输入的数据类型 也是map的value的输出  在本案例中就是数字
 * <p>
 * KEYOUT : 这是reducer输出的key数据类型 本案例中就是单词
 * <p>
 * VALUEOUT : 这是reducer输出的value数据类型 本案例中就是出现的次数
 */
public class WordCountReduce extends Reducer<Text, IntWritable, Text, IntWritable> {

    /**
     * 重写reduce,这里是单词统计
     *
     * @param key
     * @param values
     * @param context
     * @throws IOException
     * @throws InterruptedException
     *
     * reduce接受map阶段的数据后,按照key的字典顺序进行排序
     * 接着按照key相同作为一组去调用reduce方法
     * 本方法的key就是这一组相同kv对的共同k
     * 把这一组所有的v作为一个迭代器传入我们的reduce方法
     *
     * (一组一组传入,直到没有)
     */
    @Override
    protected void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {
    //调用计数器
        int count = 0;
        //遍历一组迭代器,把每一个数量1累加,就构成了总次数
        for(IntWritable value : values){
            count += value.get();//get方法把IntWritable-->int类型
        }
        //把最终的结果输出
        context.write(key,new IntWritable(count));
    }
}

  • Driver
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.CombineTextInputFormat;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.util.GenericOptionsParser;

import java.net.URI;

/**
 *这个类就是mr运行时候的主类,本类组装了一些程序运行时的信息
 *
 */
public class WordCountDriver {
    public static void main(String[] args)throws Exception {
        //通过Job这类来封装本次mr的信息
        Configuration conf = new Configuration();
        Job job = Job.getInstance(conf);

        //指定本次mrjob jar运行的主类
        job.setJarByClass(WordCountDriver.class);

        //指定本次所用的map和reduce类
        job.setMapperClass(WordCountMapper.class);
        job.setReducerClass(WordCountReduce.class);

        //指定本次mr mapper阶段的输出kv类型
        job.setMapOutputKeyClass(Text.class);
        job.setMapOutputValueClass(IntWritable.class);

        //指定reduce输出的kv类型
        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(IntWritable.class);

        //设置输出形成几个文件(有效文件)
        //这是数据分区
        job.setNumReduceTasks(1);

        //指定本次输入数据和输出数据路径
        FileInputFormat.setInputPaths(job,"D:\\input");
        //ouptu文件夹不能存在,否则会报错
        FileOutputFormat.setOutputPath(job,new Path("D:\\output"));

        //提交并且监控打印情况
        // job.submit(); 只是提交
        boolean b = job.waitForCompletion(true);//提交并且监控打印
        System.exit(b?0:1);
    }
}

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值