MapperReduce初学附加自定义输出的NameWordCount统计


前言

MapReduce的编程模型可简单分为简单编程模型和复杂编程模型,它们最大的区别在于是否使用Reduce进行规约处理


提示:以下是本篇文章正文内容

一、MapReduce是什么?

简单来说,MapReduce是一种思想,或是一种编程模型。对于Hadoop来说,MapReduce是一个分布式计算框架,是它的一个基础组件。当配置好Hadoop集群时,MapReduce就已经包含在内。

二、MapReduce编程模型

1.MapReduce简介

Hadoop MapReduce编程模型主要由两个抽象类构成,既Mapper和Reduce。Mapper用于处理切分过的原始数据,Reduce对Mapper的结果进行汇总,得到最后的输出。
在这里插入图片描述
在数据格式上,Mapper接收<key,value>格式的输入流,并产生一系列同样是<key,value>形式的输出流数据,这些输出流经过相应处理,形成<key,{value,list}>形式的中间结果;然后将这些中间结果传给Reduce作为输入数据流,对相同key值得{value list}做相应处理,最终生成<key,value>形式得输出数据流,在写入文件或者HDFS中。
<key,value>——>Mapper——><key,value>…——> <key,{value,list}>…——>Reduce——><key,value>…

当然,上面只是map和reduce的处理过程,还有一些处理流程没有提到
例如,如何把原始解析成Mapper可处理的数据,Mapper的中间结果如何分配给对应的Reduce,Reduce产生的结果数据以何种形式存储到HDFS中。

Hadoop提供的其他基本API:InputFormat(分片并格式化原始数据)、Partitioner(处理分配Mapper产生的结果数据)、OutputFormat(按指定格式写入文件),并且提供了很多可行的默认处理方式,可以满足大部分使用需求。所以很多时候只需要实现Mapper和Reduce函数即可实现基于MapReduce的分布式程序的编写。

2.Mapreduce简单模型

对于某些任务来说,可能并不一定需要Reduce过程。例如,只需要对文本的每一行数据做简单的格式转换,那么只需要由Mapper处理就行,所以MapReduce也有简单的编程模型,该模型只有Mapper过程,由Mapper产生的数据直接写入文件或HDFS。

在这里插入图片描述

MapReduce的复杂模型

对于大部分任务来说,都是需要Reduce过程,并且由于任务繁重,会启动多个Reduce(默认为1,根据任务量可由用户自己设定合适的Reduce数量)来进行汇总,如果只用一个Reduce计算所有Mapper的结果,就会导致单个Reduce负载过于繁重,形成性能瓶颈,大大增加任务的运行周期。


在这里插入图片描述

一个key值只会对应一个Reducer
在这里插入图片描述

MapReduce编程实例——WordCount

简单的写一个文件
file: text1.txt

杨超镇  陈其昇 温晋斌 邹锋 谢文艺 杨豪 方习宇 林明华
罗钦炜 罗泽健 曾梓健 袁焯轩 覃世杰 林俊雄 杨观楠 方智永
罗伟涛  陈怡帆 王健 梁忠伟 王鹏达 黄经 莫沛文 林培涌
莫伟源 黄虎 邝子贤 陈德柠 黄佳鑫 张沐鑫 钟鹏 郑凯武
简永熙 钟永锵 陈晓派 陈雨彬 周新凯 冯景杰 林泽文 侯圣杰
岑宇 谢明森  庄承阳  周镜波 邵智聪 王璟麟 梁国翔

需求:
1. 设计mapreduce程序 读取文件
2. 获得文件中名字的不同姓氏
3. 输出结果
姓氏:王=名字:王一,王二,王三,王四=共计:4人(输出必须按照次格式)

自定义Mapper

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

public class Mapper_Name extends Mapper<LongWritable, Text, Text, Text> {
    @Override
    protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
        System.out.println("___________________________Mapper______________________________");

        //InputFormat类定义了如何分割和读取输入文件,默认的输入格式是TextInputFormat.它把输入文件每一行作为单独的一个记录,但不做解析处理
        String [] split = value.toString().split("\\s+");

        for (String name : split) {
            context.write(new Text(name.substring(1,2)),new Text(name));
        }

    }
}

自定义Reduce



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

import java.io.IOException;

public class Reduce_Name extends Reducer<Text, Text, Text, Text> {


    @Override
    protected void reduce(Text key, Iterable<Text> values, Context context) throws IOException, InterruptedException {

        System.out.println(key.toString());
        long count = 0L;
        String s ="";

        for (Text text:values){
            System.out.println(text);
            count +=1;
            s +=text+",";
        }
        String s1 = s.substring(0, s.length()-1);

        context.write(new Text("姓氏:"+key+"==="+"名字:"+s1+"=====共计:"+count+"人"),new Text(""));



    }

    @Override
    public String toString() {
        return super.toString();
    }
}

启动类


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

public class Driver_Name {
    public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
        //获取配置文件中的参数
        Configuration configuration = new Configuration();
        //通过参数配置获取一个Job对象
        Job job = Job.getInstance(configuration,"NameMain");

        //启动Mapper入口
        job.setMapperClass(Mapper_Name.class);
        //启动Reduce入口
        job.setReducerClass(Reduce_Name.class);


        job.setMapOutputKeyClass(Text.class);
        job.setMapOutputValueClass(Text.class);


        // 1.7:指定reduce输出的<K,V>类型
        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(Text.class);

        //设置输入源
        String inl = "input1\\name";
        //设置输出路径
        String out = "output\\HuangYuShu";
        Path input = new Path(inl);
        Path output = new Path(out);
        //将路径加入到文件格式中
        FileInputFormat.addInputPath(job,input);
        FileOutputFormat.setOutputPath(job,output);
        System.out.println(job.waitForCompletion(true) ? 0 : 1);
    }
}

结果集
姓氏:侯=名字:侯圣杰=共计:1人
姓氏:冯
=名字:冯景杰=共计:1人
姓氏:周
=名字:周镜波,周新凯
=共计:2人
姓氏:岑
=名字:岑宇=共计:1人
姓氏:庄
=名字:庄承阳
=共计:1人
姓氏:张
=名字:张沐鑫=共计:1人
姓氏:方
=名字:方智永,方习宇
=共计:2人
姓氏:曾
=名字:曾梓健=共计:1人
姓氏:杨
=名字:杨豪,杨观楠,杨超镇
=共计:3人
姓氏:林
=名字:林培涌,林泽文,林俊雄,林明华=共计:4人
姓氏:梁
=名字:梁忠伟,梁国翔
=共计:2人
姓氏:温
=名字:温晋斌=共计:1人
姓氏:王
=名字:王鹏达,王璟麟,王健
=共计:3人
姓氏:简
=名字:简永熙=共计:1人
姓氏:罗
=名字:罗泽健,罗钦炜,罗伟涛
=共计:3人
姓氏:莫
=名字:莫沛文,莫伟源=共计:2人
姓氏:袁
=名字:袁焯轩
=共计:1人
姓氏:覃
=名字:覃世杰=共计:1人
姓氏:谢
=名字:谢明森,谢文艺
=共计:2人
姓氏:邝
=名字:邝子贤=共计:1人
姓氏:邵
=名字:邵智聪
=共计:1人
姓氏:邹
=名字:邹锋=共计:1人
姓氏:郑
=名字:郑凯武
=共计:1人
姓氏:钟
=名字:钟鹏,钟永锵=共计:2人
姓氏:陈
=名字:陈其昇,陈晓派,陈怡帆,陈德柠,陈雨彬
=共计:5人
姓氏:黄
=名字:黄经,黄虎,黄佳鑫=====共计:3人

修改于2022/5/14

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值