手写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.hqwc.cn/news/295957.html

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

相关文章

蓝牙物联网室内定位系统解决方案

目前国内外室内定位技术较多&#xff0c;常见的有无线局域网(Wireless Fidelity,WiFi)、射频识别(Radio FrequencyIdentification,RFID)、蓝牙低功耗(Bletooth Low EnergyBLE)、超宽带(Ultra Wide BandUWB)技术等。近几年智能设备的迅速发展和蓝牙设备的生产制造成本越来越低&a…

Unity手机移动设备重力感应

Unity手机移动设备重力感应 一、引入二、介绍三、测试成果X Y轴Z轴横屏的手机&#xff0c;如下图竖屏的手机&#xff0c;如下图 一、引入 大家对重力感应应该都不陌生&#xff0c;之前玩过的王者荣耀的资源更新界面就是使用了重力感应的概念&#xff0c;根据手机的晃动来给实体…

案例147:基于微信小程序的酒店管理系统

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

使用vue-qr,报错in ./node_modules/vue-qr/dist/vue-qr.js

找到node_modules—>vue-qr/dist/vue-qr.js文件&#xff0c;搜…e,将…去掉&#xff0c;然后重新运行项目。

Netty 与 RPC(一)

Netty 与 RPC Netty 原理 Netty 是一个高性能、异步事件驱动的 NIO 框架&#xff0c;基于 JAVA NIO 提供的 API 实现。它提供了对TCP、UDP 和文件传输的支持&#xff0c;作为一个异步 NIO 框架&#xff0c;Netty 的所有 IO 操作都是异步非阻塞的&#xff0c;通过 Future-List…

Github 2023-12-23 开源项目日报 Top10

根据Github Trendings的统计&#xff0c;今日(2023-12-23统计)共有10个项目上榜。根据开发语言中项目的数量&#xff0c;汇总情况如下&#xff1a; 开发语言项目数量Python项目6C项目2C项目1Jupyter Notebook项目1HTML项目1Go项目1非开发语言项目1 免费API集体清单 创建周期…

医疗影像中DR的骨抑制

1 背景 在DR的拍摄中&#xff0c;根据肺部和脊肋骨两种组织&#xff0c;在不同能量X射线的照射下&#xff0c;衰减的系数不同的特点&#xff0c;可以通过两次不同剂量的曝光后&#xff0c;通过算法&#xff0c;得到一张骨骼的图像和一张肺部图像。 通过一些机构的统计&#x…

爬虫字典生成工具,CeWL使用教程

爬虫字典生成工具,CeWL使用教程 1.工具概述2.参数解析3.使用实例1.工具概述 CeWL 是一个 ruby 应用程序,它将给定的 URL 爬到指定的深度,可以选择跟随外部链接,并返回一个单词列表,然后可用于密码破解者 Cewl 是黑客武器库中的强大工具,因为它允许创建有针对性的单词列…

Git常用命令及解释说明

目录 前言1 git config2 git init3 git status4 git add5 git commit6 git reflog7 git log8 git reset结语 前言 Git是一种分布式版本控制系统&#xff0c;广泛用于协作开发和管理项目代码。了解并熟练使用Git的常用命令对于有效地管理项目版本和历史记录至关重要。下面是一些…

鸿蒙WebGL开发入门

WebGL的全称为Web Graphic Library(网页图形库)&#xff0c;主要用于交互式渲染2D图形和3D图形。目前HarmonyOS中使用的WebGL是基于OpenGL裁剪的OpenGL ES&#xff0c;可以在HTML5的canvas元素对象中使用&#xff0c;无需使用插件&#xff0c;支持跨平台。WebGL程序是由JavaScr…

利用PySpark进行商业洞察与可视化

利用PySpark进行商业洞察与可视化 引言数据集与技术栈数据集&#xff1a;YELP数据集技术栈&#xff1a;Flask、MySQL、Echarts、PySpark 分析维度与功能创新点与应用 引言 近年来&#xff0c;数据分析和可视化技术在商业决策中的应用越来越广泛。在这个信息爆炸的时代&#xf…

网络协议-BIO实战和NIO编程

网络通信编程基本常识 原生JDK网络编程-BIO 原生JDK网络编程-NIO Buffer 的读写 向 Buffer 中写数据 写数据到 Buffer有两种方式: 1. 读取 Channel写到 Buffer。 2.通过 Buffer 的 put0方法写到 Buffer 里。 从 Channel 写到 Buffer …