手写MapReduce实现WordCount

水善利万物而不争,处众人之所恶,故几于道💦

文章目录

      • 需求
      • 分析
      • 编写MapReduce实现上述功能
        • Mapper类
        • Reducer类
        • Driver类
      • 查看输出结果

需求

  假设有一个文本文件word.txt,我们想要统计这个文本文件中每个单词出现的次数。
文件内容如下:

在这里插入图片描述
期望输出结果:
在这里插入图片描述

分析

  根据MapReduce的思想,整体分为两个过程一个是Map阶段,一个是Reduce阶段。可以粗略得出下面几步:
  ①将读取到的数据进行单词间的拆分,拆出来一个一个的单词。
  ②将每个单词出现的次数标记为1。eg:(hello,1)、(qcln,1)…
  ③然后相同单词进入一个ReduceTask,进行value值的累加,也就算出了这个单词出现的次数。
  ④将最终的结果输出。

在这里插入图片描述

编写MapReduce实现上述功能

要先添加Hadoop的项目依赖(建Maven项目)

<dependencies><dependency><!-- Hadoop的项目依赖--><groupId>org.apache.hadoop</groupId><artifactId>hadoop-client</artifactId><version>3.1.3</version></dependency><dependency><!--这个可加可不加,是为了在控制台打印日志的,加上的话要在resources目录下建一个log4j.properties配置文件--><groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId><version>1.7.30</version></dependency>
</dependencies>

resources目录下log4j.properties配置文件内容:

log4j.rootLogger=INFO,stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n
log4j.appender.logfile=org.apache.log4j.FileAppender
log4j.appender.logfile.File=target/spring.log
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] - %m%n

项目目录结构:
在这里插入图片描述

编写MapReduce程序的话要写三个类Mapper、Reducer、Driver

Mapper类:继承Mapper类,重写map方法。每行数据读进来后,他都要调用map方法对数据进行处理,处理完后,再把数据写回框架,让框架处理。

Recuder类:继承Reducer类,重写reduce方法。key值相同的数据会进入同一个reduce方法,这个阶段会调用reduce方法对这一组key值相同的数据进行处理。

Driver类:整个MapReduce程序的入口,在这个类中写main方法。这个类主要是创建一个job实例,然后给job赋值(指定Mapper类、Reducer类、Mapper输出的key value类型、最终结果输出的key value类型、Map Reduce程序的读取文件路径和结果输出路径),最后提交该job

Mapper类
package com.daemon.mr.wordcount;import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;import java.io.IOException;/*** Author: Pepsi* Date: 2023/12/21* Desc:*//*
* Mapper<KEYIN, VALUEIN, KEYOUT, VALUEOUT>泛型含义:1.偏移量:是一行中数据的偏移量,可以理解成这一行数据长度的样子。比如第一行  abcde  第二行 qwe,假如第一行的偏移量是0,第二行的偏移量可能就是8这个类型只能为LongWritable类型,偏移量比较大2.读到的每行数据的类型3.输出的key的类型  因为这里词频统计map后想要输出(aaa,2)这种形式,所以key是Text value是LongWritable类型4.输出的value的类型这个类主要的作用就是封装kv对也就是标记,也就是WordCount需求中将每行数据处理为(hello,1)这种格式
* */
public class WCMappre extends Mapper<LongWritable,Text, Text, LongWritable> {// 创建一个输出键的对象,待会儿取到数据后直接赋值给他,然后写出去// 定义在map外面就不用频繁创建对象了private Text outKey = new Text();// 创建一个输出值的对象,也就是那个频率,这里直接给他初始化为1,直接用  private LongWritable outValue = new LongWritable(1);/**** @param key 读取到每行数据的偏移量* @param value  读取到的那一行数据* @param context 上下文对象,可以理解为程序本身,因为是框架下编程,所以处理结果要还给框架* @throws IOException* @throws InterruptedException*/@Overrideprotected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {//super.map(key, value, context);//System.out.println("这是偏移量:"+key);//将读取到的一行数据转换为字符串类型(Text类型是Hadoop的类型没法切割)// 然后按照空格切分,因为要读取的数据文件中单词之间使用空格分开的String[] words = value.toString().split(" ");// 得到这一行的单词数组后,进行遍历每个单词for (String word : words) {// 将上面创建好的Text对象的值设置为当前遍历到的单词 ==> outKey=qcln  outValue=1outKey.set(word);// 写回框架,后续交给框架处理   ==> (qcln,1)context.write(outKey,outValue);}}
}
Reducer类
package com.daemon.mr.wordcount;import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;import java.io.IOException;/*** Author: Pepsi* Date: 2023/12/21* Desc:*//*
Mapper<KEYIN, VALUEIN, KEYOUT, VALUEOUT>
1.输入的key的类型 也就是Map阶段输出key的类型
2.输入的value的类型  也就是Map阶段输出的value的类型
3.最终结果输出的key的类型  也就是写出到文件中的key的类型,是单词,所以是Text类型
4.最终的结果输出的value的类型 也就是写出到文件中的value的类型,是单词出现的次数,所以是LongWritable类型(IntWritable也行,只不过如果数据量大,怕IntWritable放不下)*/
public class WCReducer extends Reducer<Text, LongWritable,Text,LongWritable> {// 用来存放单词出现的总次数,最后要将他写出去private LongWritable outVale = new LongWritable();/**** @param key map结果输出的key* @param values 相同key的所有值* @param context 上下文* @throws IOException* @throws InterruptedException*/@Overrideprotected void reduce(Text key, Iterable<LongWritable> values, Context context) throws IOException, InterruptedException {//super.reduce(key, values, context);// 累加变量,存放单词出现的总次数,待会要把这个结果赋给LongWritable,然后写出去long count = 0;// 遍历每个valuefor (LongWritable value : values) {// get()方法返回一个long类型的值count+=value.get();}// 将long类型的累加变量赋值给LongWritable => outVale=2outVale.set(count);// 将结果写出去 => (qcln,2)context.write(key,outVale);}
}
Driver类
package com.daemon.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;import java.io.IOException;/*** Author: Pepsi* Date: 2023/12/21* Desc:*/
public class WCDriver {public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {Configuration conf = new Configuration();// 1. 创建job实例,可以不传conf,传的话可以用conf.set(key,value)进行一些配置Job job = Job.getInstance(conf);// 2. 给job赋值// 设置jar的入口类,如果是本地运行可以不写,如果想要将项目打jar包扔在集群上运行必须写job.setJarByClass(WCDriver.class);// 指定Mapper和Reducer类job.setMapperClass(WCMappre.class);job.setReducerClass(WCReducer.class);// 设置Mapper输出的key value 类型job.setMapOutputKeyClass(Text.class);job.setMapOutputValueClass(LongWritable.class);// 设置整个程序输出的key value类型 -- Reducer的输出也就是整个程序的输出,所以也可以理解为Reducer的输出类型job.setOutputKeyClass(Text.class);job.setOutputValueClass(LongWritable.class);// 设置程序从哪读取文件,将结果输出到哪,输出目录不能存在FileInputFormat.setInputPaths(job,new Path("D:\\word.txt"));FileOutputFormat.setOutputPath(job,new Path("D:\\output"));// 3. 提交job,运行。 也可以不接收这个返回值boolean b = job.waitForCompletion(true);// 程序结束返回的状态码System.exit(b ? 0 : 1);}
}

查看输出结果

在这里插入图片描述在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/240185.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

「Verilog学习笔记」自动售卖机

专栏前言 本专栏的内容主要是记录本人学习Verilog过程中的一些知识点&#xff0c;刷题网站用的是牛客网 timescale 1ns/1nsmodule sale(input clk ,input rst_n ,input sel ,//sel0,5$dranks,sel1,10&$drinksinput …

JavaScript原型,原型链 ? 有什么特点?

一、原型 JavaScript 常被描述为一种基于原型的语言——每个对象拥有一个原型对象 当试图访问一个对象的属性时&#xff0c;它不仅仅在该对象上搜寻&#xff0c;还会搜寻该对象的原型&#xff0c;以及该对象的原型的原型&#xff0c;依次层层向上搜索&#xff0c;直到找到一个…

【Linux笔记】文件和目录操作

&#x1f34e;个人博客&#xff1a;个人主页 &#x1f3c6;个人专栏&#xff1a;Linux学习 ⛳️ 功不唐捐&#xff0c;玉汝于成 目录 前言 命令 ls (List): pwd (Print Working Directory): cp (Copy): mv (Move): rm (Remove): 结语 我的其他博客 前言 学习Linux命令…

案例096:基于微信小程序的社区团购系统

文末获取源码 开发语言&#xff1a;Java 框架&#xff1a;Spring Boot JDK版本&#xff1a;JDK1.8 数据库&#xff1a;mysql 5.7 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.5.4 小程序框架&#xff1a;uniapp 小程序开发软件&#xff1a;HBuilder…

python dash 的学习笔记1

dash 用python开发web界面 https://dash.plotly.com/ 官方上支持jula F# python一类。当然我只会python只学习python中使用dash. 要做一个APP&#xff0c;用php,java以及.net都可以写&#xff0c;只所有选择python是因为最近在用这一个。同时也发现python除了慢全是优点。 资料…

MES系统怎么实现车间管理中的生产计划和排产计划

MES中的生产计划和排产计划都是制造企业中非常重要的概念&#xff0c;它们的目的是为了确保企业能够按时交付高质量的产品&#xff0c;同时还要保持生产效率和成本效益。 一、生产计划 生产计划是指制造企业为了满足客户需求而制定的计划&#xff0c;它包括了制造的数量、时间…

计算机网络——计算机网络的概述(一)

前言&#xff1a; 面对马上的期末考试&#xff0c;也为了以后找工作&#xff0c;需要掌握更多的知识&#xff0c;而且我们现实生活中也已经离不开计算机&#xff0c;更离不开计算机网络&#xff0c;今天开始我们就对计算机网络的知识进行一个简单的学习与记录。 目录 一、什么…

java easyexcel上传和下载数据

安装依赖 easyexcel官方文档 <!--通过注解的方式导出excel--><dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.3.1</version></dependency>注意踩坑&#xff1a;easyexcel会…

【单调栈】LeetCode:2818操作使得分最大

作者推荐 map|动态规划|单调栈|LeetCode975:奇偶跳 涉及知识点 单调栈 题目 给你一个长度为 n 的正整数数组 nums 和一个整数 k 。 一开始&#xff0c;你的分数为 1 。你可以进行以下操作至多 k 次&#xff0c;目标是使你的分数最大&#xff1a; 选择一个之前没有选过的 非…

【已解决】Python Bresenham 3D算法

放一段使用Python实现Bresenham 3D 算法的代码&#xff0c;并通过Matplot可视化 import numpy as np import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D from numba import njitnjit def bresenham_safe(grid, x0, y0, z0, x1, y1, z1, value_to_fill…

linux系统和网络(二):进程和系统时间

本文主要探讨linux系统进程和系统相关知识&#xff0c;本博客其他博文对该文章的部分内容有详细介绍 main函数 int main(int argc,char *argv[],char *envp[]); 操作系统下main执行前先执行引导代码,编译连接引导代码和程序连接在一起构成可执行程序,加载器将程序加载到内存中…

Docker与容器化安全:漏洞扫描和安全策略

容器化技术&#xff0c;特别是Docker&#xff0c;已经成为现代应用程序开发和部署的关键工具。然而&#xff0c;容器化环境也面临着安全挑战。为了保障容器环境的安全性&#xff0c;本文将介绍如何进行漏洞扫描、制定安全策略以及采取措施来保护Docker容器。我们将提供丰富的示…

conda环境下更改虚拟环境安装路径

1 引言 在Anaconda中如果没有指定路径,虚拟环境会默认安装在anaconda所安装的目录下,但如果默认环境的磁盘空间不足&#xff0c;无法满足大量安装虚拟环境的需求&#xff0c;此时我们需要更改虚拟环境的安装路径&#xff0c;有以下两种方案&#xff1a; 方案1&#xff1a; 每次…

Linux--编写系统服务脚本

编写一个名为myprog的系统服务脚本&#xff0c;通过位置变量s1指定的start、stop、restart、status控制参数&#xff0c;分别用来启动、停止、重启sleep进程&#xff0c;以及查看sleep进程的状态。其中&#xff0c;命令sleep用来暂停指定秒数的时间&#xff0c;这里仅用做测试&…

【数据结构和算法】---栈和队列的互相实现

目录 一、用栈实现队列1.1初始化队列1.2模拟入队列1.3模拟出队列1.4取模拟的队列头元素1.5判断队列是否为空 二、用队列实现栈2.1初始化栈2.2模拟出栈2.3模拟入栈2.4取模拟的栈顶元素2.5判读栈是否为空 一、用栈实现队列 具体题目可以参考LeetCode232. 用栈实现队列 首先要想到…

SpringMVC:整合 SSM 下篇

文章目录 SpringMVC - 05整合 SSM 下篇一、设计页面1. 首页&#xff1a;index.jsp2. 展示书页面&#xff1a;showBooks.jsp3. 增加书页面&#xff1a;addBook.jsp4. 修改书页面&#xff1a;updateBook.jsp5. 总结 二、控制层1. 查询全部书2. 增加书3. 修改书4. 删除书5. 搜索书…

SpringMVC系列之技术点定向爆破二

SpringMVC的运行流程 客户端发送请求 tomcat接收对应的请求 SpringMVC的核心调度器DispatcherServlet接收到所有请求 请求地址与RequestMapping注解进行匹配&#xff0c;定位到具体的类和具体的处理方法&#xff08;封装在Handler中&#xff09; 核心调度器找到Handler后交…

成功案例分享:物业管理小程序如何助力打造智慧社区

随着科技的进步和互联网的普及&#xff0c;数字化转型已经渗透到各个行业&#xff0c;包括物业管理。借助小程序这一轻量级应用&#xff0c;物业管理可以实现线上线下服务的无缝对接&#xff0c;提升服务质量&#xff0c;优化用户体验。本文将详细介绍如何通过乔拓云网设计小程…

LeetCode刷题--- 目标和

个人主页&#xff1a;元清加油_【C】,【C语言】,【数据结构与算法】-CSDN博客 个人专栏 力扣递归算法题 http://t.csdnimg.cn/yUl2I 【C】 http://t.csdnimg.cn/6AbpV 数据结构与算法 http://t.csdnimg.cn/hKh2l 前言&#xff1a;这个专栏主要讲述递归递归、搜…

基于SSM的剧本杀预约系统(有报告)。Javaee项目。ssm项目。

演示视频&#xff1a; 基于SSM的剧本杀预约系统&#xff08;有报告&#xff09;。Javaee项目。ssm项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&#xff0c;通过Spring Sp…