MapReduce进程介绍及实际操作——计算文本中单词出现的次数

MapReduce进程

一个完整的MapReduce程序在分布式运行时有三类实例进程:

1)MrAppMaster:负责整个程序的过程调度及状态协调。

2)MapTask:负责Map阶段的整个数据处理流程。

3)ReduceTask:负责Reduce阶段的整个数据处理流程。

常用数据序列化类型

为了支持分布式计算和大规模数据处理,在Hadoop包中处理的数据类型对Java的数据类型进行了封装。

Java类型Hadoop Writable类型
BooleanBooleanWritable
ByteWritable
IntIntWritable
FloatFloatWritable
LongLongWritable
DoubleDoubleWritable
StringText
MapMapWritable
ArrayArrayWritable
NullNullWritable

MapReduce编程结构

1.Mapper阶段

(1)用户自定义的Mapper要继承hadoop中的Mapper。

(2)Mapper的输入数据是KV键值对形式(KV类型可以自定义)。

(3)具体Mapper阶段的业务代码写在重写的map()方法中。

(4)Mapper的输出数据是KV键值对形式(KV类型可以自定义)。

(5)MapTask进程对每一个<K,V>就调用一次map()方法。

2. Reduce阶段

(1)用户自定义的Reduce要继承hadoop中的Reducer。

(2)Reduce的输入数据类型对应的是Mapper的输出数据类型:KV键值对。

(3)具体Reduce阶段的业务代码写在重写的reduce()方法中。

(4)ReduceTask进程对每一组相同K的<K,V>组调用一次reduce()方法。

3. Driver阶段

相当于YARN集群的客户端,用于提交整个集群到YARN集群,提交的是封装了MapReduce程序相关运行参数的job对象。

实操——计算文本中单词出现的次数

1. 创建maven项目,导入依赖

以 Whatever is worth doing is worth doing well 为例:

我们需要完成的Map阶段和Reduce阶段的任务,以及整个mapreduce程序的入口。

对应三个Java类:WordCountMapper、WordCountReducer和WordCountDriver。

创建包 mapreduce.wordcount => 分别创建类WordCountMapper、WordCountReducer和WordCountDriver。

2. WordCountMapper.java:

假设要计算的文本内容如下:(分成两行,行数=map()函数的调用次数)

Whatever is worth doing

is worth doing well

Mapper类的四个参数:

Mapper<LongWritable, Text,Text, IntWritable>

LongWritable:

表示map函数的输入的键值对中的key的类型,值为每行文本的偏移量,第一行的偏移量为23,空格和换行符也算在内。

Text:

代表map函数的输出的键值对的value的类型,值为每一行的文本内容,比如第一行: Whatever is worth doing

Text:

代表输出键值对的key的类型,代表每个单词,第一次调用map(),值就是Whatever

IntWritable:

代表map函数的输出kv键值对的value类型,代表每个单词的出现次数,都是一次

package mapreduce.wordcount;

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;

/**
 * LongWritable:表示map函数的输入的键值对中的key的类型,值为每行文本的偏移量
 * 第一个Text:代表map函数的输出的键值对的value的类型,值为每一行的文本内容
 *
 * 第二个Text:代表输出键值对的key的类型,代表每个单词
 * IntWritable:代表map函数的输出kv键值对的value类型,代表每个单词的出现次数(1次)
 */
public class WordCountMapper extends Mapper<LongWritable, Text,Text, IntWritable> {

    //新建Text对象,该对象作为map阶段输出的kv键值对中的key
    Text keyOut = new Text();

    //新建IntWritable对象,该对象作为map阶段输出的kv键值对中的value
    IntWritable valueOut = new IntWritable(1);

    //map()方法的调用次数,取决于文本中有几行
    @Override
    protected void map(LongWritable key, Text value,Context context) throws IOException, InterruptedException {

        //获取一行文本
        String line = value.toString();

        //根据单词间的分隔符进行拆分
        String[] words = line.split(" ");

        //遍历数组
        for (String word : words) {

            //对输出kv中的key进行赋值
            keyOut.set(word);

            //map阶段处理完成,进行kv键值对的输出
            context.write(keyOut,valueOut);
        }
    }
}

3. WordCountReducer.java :

reduce()方法的执行次数 = 输入的键值对的个数 = 单词的种类数量

Reducer<Text, IntWritable,Text,IntWritable>的四个参数:

Text:

map阶段输出键值对中的key,值为单词

IntWritable:

map阶段输出键值对中的value,值为1

Text:

reduce阶段输出键值对中的key,值为单词,没变化

IntWritable:

reduce阶段输出键值对中的value,值为累加之后的总次数

在reduce()方法中:

reduce(Text key, Iterable<IntWritable> values, Reducer<Text, IntWritable, Text, IntWritable>.Context context)

Iterable<IntWritable> values 这个参数就是:(is,[1,1])这样的键值对中的[1,1]部分,对这个集合中数据累加即可得到is出现的次数。

package mapreduce.wordcount;

import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.mapreduce.Reducer;

import org.apache.hadoop.io.Text;
import java.io.IOException;

/**
 * 第一个Text:reduce阶段输入的kv键值对中的key,实际上也是map阶段输出的kv键值对中的key,值为单词
 * 第一个IntWritable:reduce阶段输入的kv键值对中的value,实际上也是map阶段输出的kv键值对中的value,值为1
 * 第二个Text:reduce阶段输出的kv键值对中的key,值为单词
 * 第二个IntWritable:reduce阶段输出的kv键值对中的value,值为对应的单词在整个文本中出现的次数。
 */

public class WordCountReducer extends Reducer<Text, IntWritable,Text,IntWritable> {

    //新建IntWritable对象,作为reduce阶段输出的键值对的value
    IntWritable valueOut = new IntWritable();

    //Iterable<IntWritable> values 这个参数就是:(is,[1,1])这样的键值对中的[1,1]部分,
    // 对这个集合中数据累加即可得到is出现的次数。
    @Override
    protected void reduce(Text key, Iterable<IntWritable> values,Context context) throws IOException, InterruptedException {

        //单词出现的总次数
        int totalCount = 0;

        //对单词出现的次数进行累加
        for (IntWritable value : values) {

            totalCount += value.get();
        }

        //对reduce阶段输出的value进行赋值
        valueOut.set(totalCount);

        //reduce阶段同级完成,将结果输出
        context.write(key,valueOut);
    }
}

 4. WordCountDriver.java:

package mapreduce.wordcount;

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.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

import java.io.IOException;

//作为整个mapreduce程序的入口 进行相关程序参数的设置
public class WordCountDriver {

    public static void main(String[] args) throws IOException, InterruptedException, ClassNotFoundException {

        //1. 获取配置信息对象和job对象
        Configuration conf = new Configuration();
        Job job = Job.getInstance(conf);

        //2. 关联Driver类
        job.setJarByClass(WordCountDriver.class);

        //3. 设置mapper和reducer的类
        job.setMapperClass(WordCountMapper.class);
        job.setReducerClass(WordCountReducer.class);

        //4. 设置mapper输出的键值对类型
        job.setMapOutputKeyClass(Text.class);
        job.setMapOutputValueClass(IntWritable.class);

        //5. 设置最终输出(Reducer)的键值对类型
        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(IntWritable.class);

        //6. 设置文件的输入路径和计算结果的输出路径

        //要计算的文件路径,可以同时计算多个文件
        Path file = new Path("D:\\Course\\bigdata\\bigdata-file\\word.txt");
        Path file1 = new Path("D:\\Course\\bigdata\\bigdata-file\\word2.txt");

        FileInputFormat.setInputPaths(job,file,file1);
        //设置计算结果的输出路径(这个目录要不存在)
        Path outputPath = new Path("D:\\Course\\bigdata\\bigdata-file\\output");

        FileOutputFormat.setOutputPath(job,outputPath);

        //7. 提交任务进行计算
        boolean result = job.waitForCompletion(true);

        System.out.println(result ? "任务执行成功":"任务执行失败");
    }
}

 5. 运行测试

1)文件中内容

2)运行程序

 

  • 9
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,这是一个比较经典的问题,实现MapReduce的WordCount单词词汇统计可以分为以下几个步骤: 1. Map阶段:将输入的文本文件按照空格或其他分隔符进行分割,每个分割出来的单词作为key,值为1,即将每个单词映射为(key, value)键值对。 2. Shuffle阶段:将Map阶段输出的键值对按照key进行排序,并将相同key的value合并为一个数组。 3. Reduce阶段:对每个key的values数组进行遍历,将其的值累加即可得到该单词的词频。 以下是MapReduce的WordCount单词词汇统计的Java代码示例: ```java public class WordCount { public static class Map extends Mapper<LongWritable, Text, Text, IntWritable> { private final static IntWritable one = new IntWritable(1); private Text word = new Text(); public void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException { String line = value.toString(); StringTokenizer tokenizer = new StringTokenizer(line); while (tokenizer.hasMoreTokens()) { word.set(tokenizer.nextToken()); context.write(word, one); } } } public static class Reduce extends Reducer<Text, IntWritable, Text, IntWritable> { public void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException { int sum = 0; for (IntWritable val : values) { sum += val.get(); } context.write(key, new IntWritable(sum)); } } public static void main(String[] args) throws Exception { Configuration conf = new Configuration(); Job job = Job.getInstance(conf, "wordcount"); job.setJarByClass(WordCount.class); job.setMapperClass(Map.class); job.setCombinerClass(Reduce.class); job.setReducerClass(Reduce.class); job.setOutputKeyClass(Text.class); job.setOutputValueClass(IntWritable.class); FileInputFormat.addInputPath(job, new Path(args[0])); FileOutputFormat.setOutputPath(job, new Path(args[1])); System.exit(job.waitForCompletion(true) ? 0 : 1); } } ``` 以上就是MapReduce的WordCount单词词汇统计的实现过程和Java代码示例。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值