单词计数案例

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>org.example</groupId>
    <artifactId>mapreduce_code</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <hadoop.version>2.8.5</hadoop.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-common</artifactId>
            <version>${hadoop.version}</version>
        </dependency>

        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-client</artifactId>
            <version>${hadoop.version}</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

WCMapper

package com.sxuek;

import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;
import java.io.IOException;

/**
 * 单词计数案例的Mapper的任务逻辑
 * 1. 自定义一个类继承Mapper类
 * 2. 输入数据类型:默认是以每一行的偏移量为key,每一行的数据为value<key:long, value:String>
 *    输出数据类型<key:string, value:long>
 *     mapreduce是分布式计算的,mr程序计算的数据会跨网络,跨主机传输,
 *     一旦涉及到跨网络跨主机传输,
 *     我们要求,数据类型必须实现序列化机制--不能是java的,得是Hadoop的序列化机制
 *     Java基本数据类型都有对应的Hadoop序列化类
 *     int -- IntWritable
 *     long -- LongWritable
 *     String -- Text
 * 3. 重写一个map方法,编写map阶段的逻辑
 *
 */
public class WCMapper extends Mapper<LongWritable, Text, Text, LongWritable> {
    /**
     * 默认情况下,mapper任务一个数据切片启动一个map任务,数据切片有很多行数据,
     * 一行数据会执行一次map方法
     * @param key
     * @param value
     * @param context
     * @throws IOException
     * @throws InterruptedException
     */
    @Override
    protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
        String[] s = value.toString().split(" ");
        for (String str: s) {
            // 将数据输出到下一个阶段
            context.write(new Text(str), new LongWritable(1L));
        }
    }
}

WCReducer

package com.sxuek;

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

import java.io.IOException;

/**
 * reduce阶段的逻辑执行
 * 1. 继承Reducer类  定义一下reducer阶段输入和输出keyvalue类型
 * 2. reducer阶段在mapper阶段之后,mapper的输出类型是reducer的输入类型
 */
public class WCReducer extends Reducer<Text, LongWritable, Text, LongWritable> {
    /**
     * reduce方法是一组相同的key执行一次reduce方法
     * @param key 输入的key值
     * @param values 是相同key值的value值的value数据的集合
     * @param context 上下文对象
     * @throws IOException
     * @throws InterruptedException
     */
    @Override
    protected void reduce(Text key, Iterable<LongWritable> values, Context context) throws IOException, InterruptedException {
        long count = 0L;
        for (LongWritable value: values) {
            long num = value.get();
            count += num;
        }
        context.write(key, new LongWritable(count));
    }
}

WCDriver驱动类的实现

package com.sxuek;

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;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;

/**
 * 驱动类,是一个可以运行的main方法
 *
 * mr程序编写完成有两种运行方式
 * 1. 在IDEA中直接右键运行----此时MR程序资源由本地CPU分配,而且不是分布式执行
 * 使用场景
 * ①用于测试代码能不能正常运行的时候使用
 * ②数据量比较小的时候使用
 * 2. 将代码打成jar包上传到HADOOP集群,交给yarn运行
 */
public class WCDriver {
    public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException, URISyntaxException {
        /**
         * 需要将mapper阶段和reduce阶段的代码关联起来
         * 并且指定MR程序处理的数据以及输出的数据
         */
        // 1. 准备配置文件对象
        Configuration conf = new Configuration();
        // 设置一下hdfs的地址
        conf.set("fs.defaultFS", "hdfs://node1:9000");

        // 2. 准备一个用于封装MR程序的JOB类--用于关联mr的各个组件
        Job job = Job.getInstance(conf); // 获取job实例

        // 3. 通过JOB封装Mapper程序
        job.setMapperClass(WCMapper.class);
        // 设置map阶段输出的key类型
        job.setMapOutputKeyClass(Text.class);
        job.setMapOutputValueClass(LongWritable.class);

        // 4. 通过job封装reducer程序
        job.setReducerClass(WCReducer.class);
        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(LongWritable.class);

        // 5. 封装处理的输入文件路径 FileInputFormat
        // 算两个路径下的文件中的单词出现的总次数
        FileInputFormat.setInputPaths(job, new Path("/wc.txt"), new Path("/p/wc.txt"));

        // 6. 封装处理完成数据的输出文件路径--FileOutputFormat
        // 输出路径的文件夹一旦不能存在,如果存在代码报错
//        FileOutputFormat.setOutputPath(job, new Path("/output"));
        Path path = new Path("/output");
        FileSystem fs = FileSystem.get(new URI("hdfs://node1:9000"), conf, "root");
        if (fs.exists(path)) {
            fs.delete(path, true);
        }
        FileOutputFormat.setOutputPath(job, path);

        // 7. 代码提交运行
        boolean flag = job.waitForCompletion(true);
        if (flag) {
            System.out.println("成功"+flag);
        } else {
            System.out.println("失败"+flag);
        }
    }
}

运行

方式一 直接运行驱动类,成功
方式二 将项目打成jar包,在linux中用命令执行
# 将项目打成jar包,上传
[root@node1 data]# rz

[root@node1 data]# ll
总用量 12
-rw-r--r--. 1 root root 5219 7月  25 10:51 mapreduce_code-1.0-SNAPSHOT.jar
-rw-r--r--. 1 root root  108 7月  25 09:32 wc.txt

# 运行jar包
[root@node1 data]# hadoop jar mapreduce_code-1.0-SNAPSHOT.jar com.sxuek.WCDriver

# 报错找不到Error: java.lang.RuntimeException: java.lang.ClassNotFoundException: Class com.sxuek.WCMapper not found
# 解决:在WCDriver类中添加如下代码
job.setJarByClass(WCDriver.class);

posted @ 2022-07-25 11:14  jsqup  阅读(25)  评论(0编辑  收藏  举报