mapreduce入门之wordcount案例

MapReduce入门之wordcount案例

1 pom.xml的配置

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>cn.itcast.bigdata</groupId>
    <artifactId>example-mr</artifactId>
    <version>1.0</version>
    <dependencies>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-common</artifactId>
            <version>2.7.4</version>
        </dependency>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-hdfs</artifactId>
            <version>2.7.4</version>
        </dependency>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-client</artifactId>
            <version>2.7.4</version>
        </dependency>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-mapreduce-client-core</artifactId>
            <version>2.7.4</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <version>2.4</version>
                <configuration>
                    <archive>
                        <manifest>
                            <addClasspath>true</addClasspath>
                            <classpathPrefix>lib/</classpathPrefix>
                            <mainClass>cn.itcast.mr.wordcount.WordCountClient</mainClass>
                        </manifest>
                    </archive>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.0</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

2 WordCountMapper类

package cn.itcast.mr.wordcount;

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

import java.io.IOException;
import java.io.Serializable;

/**
 * @description: 此类就是MapReduce程序中mapper阶段业务逻辑处理的类 也就是maptask
 * @author: Allen Woon
 * @time: 2020/5/20 14:18
 * todo KEYIN, VALUEIN, KEYOUT, VALUEOUT
 *      KEYIN:      mapper输入kv中k的数据类型 在默认组件下  是每行起始偏移量 long
 *      VALUEIN:   mapper输入kv中v的数据类型 在默认组件下  是每行内容 String
 *      KEYOUT:    mapper输出kv中k的数据类型  本需求中 是单词  String
 *      VALUEOUT: mapper输出kv中v的数据类型  本需求中 是单词的次数1  long
 *  todo mapreduce使用默认的组件TextInputFormat读取数据,行为:一行一行的读数据。
 *          k:这一行起始位置的偏移量 offset
 *          v:这一行内容
 *
 *  todo  String long等数据类型是java的数据类型。在网络传递数据的时候需要序列化
 *  todo  但是hadoop认为java序列化机制()效率不高 甚至觉得臃肿。因此hadoop自己封装了序列化机制(Writable) 并且提供了相关的数据类型
 *
 *  java         hadoop(org.apache.hadoop.io)
 *  long----->  longWritable
 *  String--->  Text
 *  double--->  DoubleWritable
 *  null----->  nullWritable
 */
public class WordCountMapper extends Mapper<LongWritable, Text,Text,LongWritable>{

    /**
     *todo   map方法就是mapper阶段具体业务逻辑处理的方法
     *todo   TextInputFormat读取一行数据 封装成一个kv对 调用一次map方法。   读一行调用一次处理一次
     */
    @Override  //<0,hello tom hello>  ----> <hello,1> <tom,1> <hello,1>
    protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
        //把value转换成为String类型 也就是这一行的数据内容
        String line = value.toString();//hello tom hello
        //根据分隔符切割改行数据内容
        String[] words = line.split("\\s+");// [hello ,tom ,hello]
        //遍历数组 每个单词都标记1
        for (String word : words) {
            //todo  使用MapReduce程序封装的上下文对象context 把数据写出去
            context.write(new Text(word),new LongWritable(1));  //<hello,1> <tom,1> <hello,1>
        }
    }
}

3 WordCountReducer

package cn.itcast.mr.wordcount;

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

import java.io.IOException;

/**
 * @description: 此类就是MapReduce程序中reducer阶段业务逻辑处理的类 也就是reducetask
 * @author: Allen Woon
 * @time: 2020/5/20 15:14
 *
 * KEYIN,VALUEIN,KEYOUT,VALUEOUT
 *
 *      KEYIN:表示的是reducer阶段输入kv中k的类型  也就是mapper输出中k的类型。 本需求中就是单词 Text
 *      VALUEIN:表示的是reducer阶段输入kv中v的类型 也就是mapper输出中v的类型。 本需求中就是单词次数1  longWritable
 *      KEYOUT: 表示的是reducer阶段输出kv中k的类型   本需求中是单词  Text
 *      VALUEOUT 表示的是reducer阶段输出kv中v的类型  本需求中是单词总次数  longWritable
 */
public class WordCountReducer extends Reducer<Text, LongWritable,Text,LongWritable> {

    /**
     *todo mapper阶段输出的所有数据来到reduce阶段到底是如何处理的呢?
     *   <hello,1> <tom,1> <hello,1><tom,1> <hello,1>
     *
     * todo 1、排序  key的字典序进行排序 a-z  0-9
     *   <hello,1><hello,1><hello,1><tom,1><tom,1>
     * todo 2、分组  key相同的分为一组
     *   <hello,1><hello,1><hello,1>
     *   <tom,1><tom,1>
     * todo 3、同一组的数据组成一个新的kv对  一组去调用一次reduce方法。
     *          todo:新k:这组共同的key   新v:这一组所有的value组成的一个迭代器Iterable
     *   <hello,1><hello,1><hello,1>---->  <hello,[1,1,1]>
     *   <tom,1><tom,1>----------------->  <tom,[1,1]>
     *   <zip,1> ----------------------->  <zip,[1]>
     */
    @Override
    protected void reduce(Text key, Iterable<LongWritable> values, Context context) throws IOException, InterruptedException {
        //定义个统计变量
        long count =0;   //<hello,[1,1,1]>
        //遍历vlues的迭代器 取值累计求和
        for (LongWritable value : values) {
            count += value.get();
        }
        //todo  使用上下文对象Context 把数据写出去
        context.write(key,new LongWritable(count)); // <hello,3>
    }
}

4WordCountClient

package cn.itcast.mr.wordcount;

import org.apache.hadoop.conf.Configuration;
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;

/**
 * @description: 该类就是MapReduce程序运行时主类 用于各种参数属性的指定设置 任务提交动作
 * @author: Allen Woon
 * @time: 2020/5/20 15:37
 */
public class WordCountClient {
    public static void main(String[] args) throws Exception{
        //配置文件对象
        Configuration conf = new Configuration();
        //指定MapReduce程序运行的模式
        conf.set("mapreduce.framework.name","local");

        //创建job对象实例 用于属性封装 任务的提交
        Job job = Job.getInstance(conf, "WordCount");

        //指定本次mr程序运行的主类
        job.setJarByClass(WordCountClient.class);

        //指定本次mr运行的mapper类 reducer类
        job.setMapperClass(WordCountMapper.class);
        job.setReducerClass(WordCountReducer.class);

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

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

        //todo 设置reducetask个数
//        job.setNumReduceTasks(3);


        //指定本次mr程序输入 输出的数据路径
        FileInputFormat.setInputPaths(job,new Path("D:\\datasets\\wordcount\\input"));
        FileOutputFormat.setOutputPath(job,new Path("D:\\datasets\\wordcount\\output5"));

        //todo 提交job  submit()提交之后 客户端就和执行的程序断开了链接 无法实时获取程序执行的情况
//        job.submit();
        boolean result = job.waitForCompletion(true);// true表示开启监控并打印程序执行的信息
        //根据返回的结果 决定程序如何退出  如果执行程序 正常状态码0退出  否则1异常退出。
        System.exit(result ? 0 :1);
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值