hadoop03

news2024/11/25 3:38:48

MapReduce是Hadoop系统核心组件之一,它是一种可用于大数据并行处理的计算模型、框架和平台,主要解决海量数据的计算,是目前分布式计算模型中应用较为广泛的一种。

练习:计算a.txt文件中每个单词出现的次数

hello world
hello hadoop
hello 51doit
hadoop mapreduce
mapreduce spark
​
​
public class WordCount {
    public static void main(String[] args) throws IOException {
        //获取到resource文件夹下a.txt的路径
        URL resource = WordCount.class.getClassLoader().getResource("a.txt");
        String path = resource.getPath();
        //使用FileUtils将文件读取成字符串
        String s = FileUtils.readFileToString(new File(path),"utf-8");
        //将文件使用空格进行切割  \s可以切割 空格 tab键
        String[] arr = s.split("\\s+");
​
        //创建Map集合
        Map<String,Integer> map = new HashMap<>();
​
        //遍历数组
        for (String s1 : arr) {
            //判断集合是否包含指定键
            if(!map.containsKey(s1)){
                //如果不包含 添加 单词 1
                map.put(s1,1);
            }else{
                //如果包含  获取当前键的次数 +1 在添加回集合
                Integer count = map.get(s1);
                map.put(s1,count+1);
            }
        }
​
        System.out.println(map);
    }
}

通过以上的方式 计算出来了a.txt文件中每个单词出现的次数,但是我们想一下 ,如果a.txt文件非常大,怎么办?

比如有一个a.txt文件10个T的大小。这时一台计算机就没有办法计算了,因为我们根本存储不了,计算不了,那么一台计算机无法计算,就使用多台计算机来进行计算!

1.1 MapReduce核心思想

MapReduce的核心思想是“分而治之”。所谓“分而治之”就是把一个复杂的问题,按照一定的“分解”方法分为等价的规模较小的若干部分,然后逐个解决,分别找出各部分的结果,把各部分的结果组成整个问题的结果,这种思想来源于日常生活与工作时的经验,同样也完全适合技术领域。

为了更好地理解“分而治之”思想,我们光来举一个生活的例子。例如,某大型公司在全国设立了分公司,假设现在要统计公司今年的营收情况制作年报,有两种统计方式,第1种方式是全国分公司将自己的账单数据发送至总部,由总部统一计算公司今年的营收报表:第2种方式是采用分而治之的思想,也就是说,先要求分公司各自统计营收情况,再将统计结果发给总部进行统一汇总计算。这两种方式相比,显然第2种方式的策略更好,工作效率更高效。

MapReduce 作为一种分布式计算模型,它主要用于解决海量数据的计算问题。使用MapReduce操作海量数据时,每个MapReduce程序被初始化为一个工作任务,每个工作任务可以分为Map 和l Reducc两个阶段,具体介绍如下:

Map阶段::负责将任务分解,即把复杂的任务分解成若干个“简单的任务”来行处理,但前提是这些任务没有必然的依赖关系,可以单独执行任务。

Reduce阶段:负责将任务合并,即把Map阶段的结果进行全局汇总。下面通过一个图来描述上述MapReduce 的核心思想。

 

MapReduce就是“任务的分解与结和的汇总”。即使用户不懂分布式计算框架的内部运行机制,但是只要能用Map和 Reduce思想描述清楚要处理的问题,就能轻松地在Hadoop集群上实现分布式计算功能。

1.2 MapReduce编程模型

MapReduce是一种编程模型,用于处理大规模数据集的并行运算。使用MapReduce执行计算任务的时候,每个任务的执行过程都会被分为两个阶段,分别是Map和Reduce,其中Map阶段用于对原始数据进行处理,Reduce阶段用于对Map阶段的结果进行汇总,得到最终结果。

MapReduce简易模型

 MapReduce编程模型借鉴了函数式程序设计语言的设计思想,其程序实现过程是通过map()和l reduce()函数来完成的。从数据格式上来看,map()函数接收的数据格式是键值对,生的输出结果也是键值对形式,reduce()函数会将map()函数输出的键值对作为输入,把相同key 值的 value进行汇总,输出新的键值对。接下来,通过一张图来描述MapReduce的简易数据流模型。

(1)将原始数据处理成键值对<K1,V1>形式。

(2)将解析后的键值对<K1,V1>传给map()函数,map()函数会根据映射规则,将键值对<K1,V1>映射为一系列中间结果形式的键值对<K2,V2>。

(3)将中间形式的键值对<K2,V2>形成<K2,{V2,....>形式传给reduce()函数处理,把具有相同key的value合并在一起,产生新的键值对<K3,V3>,此时的键值对<K3,V3>就是最终输出的结果。

这里需要说明的是,对于某些任务来说,可能不一定需要Reduce过程,也就是说,MapReduce 的数据流模型可能只有Map 过程,由 Map产生的数据直接被写入HDFS中。但是,对于大多数任务来说,都是需要Reduce 过程的,并且可能由于任务繁重,需要设定多个 Reduce,例如,下面是一个具有多个Map 和Reduce的 MapReduce模型.

1.3 WorldCount词频统计案例

1.3.1 序列化知识点补充

因为我们的数据都存储在不同的计算机中,那么将对象中的数据从网络中传输,就一定要用到序列化!

/*
    JDK序列化对象的弊端 
    我们进行序列化 其实最主要的目的是为了 序列化对象的属性数据
    比如如果序列化一个Person对象 new Person("柳岩",38); 其实我们想要的是 柳岩 38
    但是如果直接序列化一个对象的话 JDK为了反序列化方便 会在文件中加入其他的数据 这样
    序列化后的文件会变的很大,占用空间
*/
public class Test {
    public static void main(String[] args) throws Exception {
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("d:\\person.txt"));
​
        //JDK序列化对象 
        Person p = new Person();
        p.setName("柳岩");
        p.setAge(38);
        oos.writeObject(p);
        oos.close();
    }
}

本来其实数据就占几个字节,序列化后,多占用了很多字节,这样如果序列化多的话就会浪费很多空间.

/*
    我们可以通过序列化属性的方式解决问题
    只序列化属性 这样可以减小序列化后的文件大小
*/
public class Test {
    public static void main(String[] args) throws Exception {
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("d:\\person.txt"));
​
        Person p = new Person();
        p.setName("柳岩");
        p.setAge(38);
​
        //只序列化属性
        oos.writeUTF(p.getName());
        oos.writeInt(p.getAge());
        oos.close();
    }
}
​

/*
    需要注意
    反序列化时 需要按照序列化的顺序来反序列化
*/
public class Test {
    public static void main(String[] args) throws Exception {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("d:\\person.txt"));
        //先反序列化name 在反序列化age
        String name = ois.readUTF();
        int age = ois.readInt();
        System.out.println(name + " "+age);
        ois.close();
    }
}

Hadoop对java的序列化又进行了优化,对一些类型进行了进一步的封装,方便按照自己的方式序列化

Integer  ----> IntWritable
Long     ----> LongWritable
String   ----> Text
Double   ----> DoubleWritable
Boolean  ----> BooleanWritable

1.3.2 WorldCount代码编写

map函数定义

/*
    KEYIN: K1   
    VALUIN: V1  
    KEYOUT:K2   
    VALUEOUT:V2 
*/
public class Mapper<KEYIN, VALUEIN, KEYOUT, VALUEOUT> {
  
   protected void map(KEYIN key, VALUEIN value, Mapper<KEYIN, VALUEIN, KEYOUT, VALUEOUT>.Context        context) throws IOException, InterruptedException {
            
    }
}

我们只需要继承Mapper类,重写map方法就好

import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;
​
import java.io.IOException;
​
/*
     K1 : 行起始位置   数字 Long  ---- > LongWritable
     V1 : 一行数据  字符串 String  -----> Text
     K2 : 单词     字符串 String  ----->  Text
     V2 : 固定数字1 数组  Long -----> LongWritable
 */
public class WordCountMapper  extends Mapper<LongWritable, Text,Text,LongWritable> {
​
​
    /**
     *
     * @param key   K1
     * @param value V1
     * @param context  上下文对象 将map的结果 输出给reduce
     */
    @Override
    protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
        //将一行数据 转换成字符串 按照空格切割 
        String[] arr = value.toString().split("\\s+");
        for (String k2 : arr) {
              //将单词输出给reduce
              context.write(new Text(k2),new LongWritable(1));
        }
    }
}
​

reduce函数定义

/*
    KEYIN:K2 
    VALUEIN:V2
    KEYOUT:K3
    VALUEOUT:V3
*/
public class Reducer<KEYIN, VALUEIN, KEYOUT, VALUEOUT> {
  
    protected void reduce(KEYIN key, Iterable<VALUEIN> values, Reducer<KEYIN, VALUEIN, KEYOUT,                  VALUEOUT>.Context context) throws IOException, InterruptedException {
​
    }
}

我们只需要继承Reducer类型重写reduce方法就好

/*
    K2:单词        String  ----> Text
    V2:固定数字 1   Long    ----> LongWritable
    K3:单词        String  ----> Text
    V3:相加后的结果 Long    ----> LongWritable
 */
public class WordCountReducer extends Reducer<Text,LongWritable,Text,LongWritable> {
​
    /**
     *
     * @param key  K2
     * @param values  V2的集合 {1,1,1,1}
     * @param context 上下文对象 输出结果
     */
    @Override
    protected void reduce(Text key, Iterable<LongWritable> values, Context context) throws IOException, InterruptedException {
​
        int count = 0;
        //将次数相加
        for (LongWritable value : values) {
               count+=value.get();
        }
        //写出 k3 v3
        context.write(key,new LongWritable(count));
    }
}

最后编写启动程序

​
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.*;
​
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 Test {
    public static void main(String[] args) throws IOException, InterruptedException, ClassNotFoundException {
        //创建配置对象
        Configuration conf = new Configuration();
        //创建工作任务
        Job job = Job.getInstance(conf, "wordCount");
​
        //设置Map类
        job.setMapperClass(WordCountMapper.class);
        //设置Reduce类
        job.setReducerClass(WordCountReducer.class);
​
        //设置map的输出类型
        job.setMapOutputKeyClass(Text.class);
        job.setMapOutputValueClass(LongWritable.class);
​
        //设置reduce的输出类型
        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(LongWritable.class);
​
        //设置读取文件位置  可以是文件 也可以是文件夹
        FileInputFormat.setInputPaths(job,new Path("d:\\work\\abc"));
        //设置输出文件位置
        FileOutputFormat.setOutputPath(job,new Path("d:\\work\\abc\\out_put"));
​
        //提交任务 并等待任务结束
        job.waitForCompletion(true);
    }
}
​
如果抛这个异常 需要查看windows环境
Exception in thread "main"java.lang .UnsatisfiedLinkError: org.apache .hadoop.io.nativeio.NativeIO$windows.access0(Ljava/lang/string;1) .
 如果已经配置了环境 还不行 在src新建包 org.apache.hadoop.io.nativeio
 然后hadoop02文件夹中的 NativeIO.java添加到这个包下 重新运行尝试

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

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

相关文章

Android View 事件分发机制,看这一篇就够了

在 Android 开发当中&#xff0c;View 的事件分发机制是一块很重要的知识。不仅在开发当中经常需要用到&#xff0c;面试的时候也经常被问到。 如果你在面试的时候&#xff0c;能把这块讲清楚&#xff0c;对于校招生或者实习生来说&#xff0c;算是一块不错的加分项。对于工作…

三种方式在HTML使用阿里字体图标--iconfont阿里巴巴矢量图标库

好久没用到阿里巴巴的图标&#xff0c;突然要用到就发现不会用了&#xff0c;只会导出png格式的图标png了 目录 1、字体图标 方法一、本地使用通过类名使用阿里矢量图标 1、把图标添加入库 2、把图标添加到项目 3、下载字体图标 4、使用文件 5、在对应的HTML页面上引入…

瑞吉外卖项目笔记01——环境搭建、后台登录功能

1.1 数据库 数据库&#xff1a; 创建一个空白数据库reggie&#xff0c;然后导入执行SQL文件创建的表如下&#xff1a; 1.2 项目依赖 项目依赖&#xff1a; pom.xml文件内的依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"…

国外APP项目的上线流程

现在很多创业者希望自己的项目能走出国内&#xff0c;向全球各地发展&#xff0c;尤其对于一些通用APP来说&#xff0c;国外可以增加一个新的收入渠道。比如常见的出海APP有小型游戏、手机清理、杀毒软件等等&#xff0c;这些类型的APP在全球的使用基本都是一样的&#xff0c;因…

Lucene(1):Lucene介绍

Lucene官网&#xff1a; http://lucene.apache.org/ 1 搜索技术理论基础 1.1 lucene优势 原来的方式实现搜索功能&#xff0c;我们的搜索流程如下图&#xff1a; 上图就是原始搜索引擎技术&#xff0c;如果用户比较少而且数据库的数据量比较小&#xff0c;那么这种方式实现搜…

Lucene(2):Lucene全文检索的流程

1 索引和搜索流程图 &#xff08;1&#xff09;绿色表示索引过程&#xff0c;对要搜索的原始内容进行索引构建一个索引库&#xff0c;索引过程包括&#xff1a; 确定原始内容即要搜索的内容 获得文档创建文档分析文档索引文档 &#xff08;2&#xff09;红色表示搜索过程&…

win10安装conda

conda是一个开源的软件包管理系统和环境管理系统&#xff0c;用于安装、管理和升级各种软件和应用程序。它可以在多个操作系统上运行&#xff0c;支持数百种语言和各种计算机程序。conda提供了安装软件包、创建和管理虚拟环境、配置依赖关系等功能&#xff0c;并且可以轻松地在…

Mac+Vscode+PyQt

纵览 1、需要安装Python&#xff0c;而我安装了Anaconda&#xff0c;并建立了一个虚拟环境env_qt2、在Vscode的终端中利用命令&#xff1a;3、在Vscode的扩展中安装「PYQT Integration」插件&#xff0c;4、可以在bin文件夹下创建一个无后缀的文件des&#xff0c;输入&#xff…

Hacking The Box----Awkward

信息收集 nmap扫描&#xff0c;发现22号端口和80号端口打开&#xff0c;80号端口上运行着http服务器。访问ip后URL变为hat-valley.htb 修改/etc/hosts文件&#xff0c;添加10.10.11.185 hat-valley.htb&#xff0c;然后就能正常访问网站。可以看到是一家卖帽子的公司的网站&a…

Windows如何安装使用curl命令

一、前言 个人主页: ζ小菜鸡大家好我是ζ小菜鸡&#xff0c;让我们一起学习Windows如何安装使用curl命令。如果文章对你有帮助、欢迎关注、点赞、收藏(一键三连) 二、Curl是什么 curl命令网络应用curl命令是一个利用URL规则在命令行下工作的文件传输工具。 CURL支持的通信协议…

【从零开始学Skynet】高级篇(一):Protobuf数据传输

1、什么是Protobuf Protobuf是谷歌发布的一套协议格式&#xff0c;它规定了一系列的编码和解 码方法&#xff0c;比如对于数字&#xff0c;它要求根据数字的大小选择存储空间&#xff0c;小于等于15的数字只用1个字节来表示&#xff0c;大于15的数用2个字节表示&#xff0c;以此…

PBR核心理论与渲染原理

基于物理的渲染&#xff08;Physically Based Rendering&#xff0c;PBR&#xff09;是指使用基于物理原理和微平面理论建模的着色/光照模型&#xff0c;以及使用从现实中测量的表面参数来准确表示真实世界材质的渲染理念。 以下是对PBR基础理念的概括&#xff1a; 微平面理论…

Datax的使用说明及入门操作案例演示

1.DataX DataX 是阿里云 DataWorks数据集成 的开源版本&#xff0c;在阿里巴巴集团内被广泛使用的离线数据同步工具/平台。DataX 实现了包括 MySQL、Oracle、OceanBase、SqlServer、Postgre、HDFS、Hive、ADS、HBase、TableStore(OTS)、MaxCompute(ODPS)、Hologres、DRDS, dat…

power shell 入门

常用命令 powershell版本 不区分大小写: $psversiontable $psv + tab 自动补齐 // ps version get-command 或者 gcm //获取所有命令 get-help 命令名 // 获取命令帮助信息 路径相关 get-location 或者 gl 或者 pwd // 获取当前路径 pwd: print work directory 的缩写.

Linux命令易混淆(看到新知识点就更新)

DNS相关 在Linux操作系统中&#xff0c;TCP/IP网络是通过若干个文本文件进行配置的。系统在启动时通过读取一组有关网络配置的文件和脚本参数内容&#xff0c;来实现网络接口的初始化和控制过程&#xff0c;这些文件和脚本大多数位于/etc目录下。 Linux下配置dns的三种方法 1…

深入了解梯度消失与梯度爆炸

本文探讨深度学习中经常会提到的概念–梯度消失与梯度爆炸。他们是影响模型收敛&#xff0c;学习好坏的一个重要因素&#xff0c;对此现象也提出了对应的解决方案。在此记录其概念&#xff0c;原因和相关的解决方案&#xff0c;仅供参考。 目录 概念原因解决方案1. 参数初始化2…

Vim学习笔记【Ch00,Ch01】

Vim学习笔记 GitHub的Learn-Vim仓库学习笔记Ch00 前言Ch01 Starting VimVim的官方链接Windows10下载和安装VimVim初级使用打开Vim退出Vim保存文件打开文件帮助文档helpargument参数打开多个窗口暂停 GitHub的Learn-Vim仓库学习笔记 仓库地址&#xff1a;https://github.com/ig…

Qt--数据库--增删改查操作

目录 1. Qt数据库简介 2. 连接与关闭 3. 建表 dialog.h dialog.cpp dialog.ui 4. 增删改 1.添加数据 dialog.h dialog.cpp 2.删除数据 dialog.h dialog.cpp 3.修改数据 dialog.h dialog.cpp 5. 查询 dialog.h dialog.cpp 判断数据是否存在 dialog.h dialog.cpp 1. Qt数据库简介…

如何在IVD行业运用IPD?

IVD&#xff08;体外诊断&#xff0c;In Vitro Diagnostic&#xff09;是指对人体样本&#xff08;血液、体液、组织&#xff09;进行定性或定量的检测&#xff0c;进而判断疾病或机体功能的诊断方法。IVD目前已经成为疾病预防、诊断治疗必不可少的医学手段&#xff0c;约80%左…

ChatGPT国内使用办法,无需魔法上网,免费使用ChatGPT,长期更新!!

新建了一个网站 每天给大家更新可用的免翻国内可用chatGPT https://ai.weoknow.com/ 2023.5.7新增一个 软件名称ChatGPT✦ ▌ 软件摘要 软件名称&#xff1a;ChatGPT 适用设备&#xff1a;浏览器 文件大小&#xff1a;0MB ▌ 软件简介 ChatGPT非常强大&#xff0c;但国内合…