hadoop 第一个 mapreduce 程序(对MapReduce的几种固定代码的理解)
1.2MapReduce 和 HDFS 是如何工作的
MapReduce 其实是两部分,先是 Map 过程,然后是 Reduce 过程。从词频计算来
说,假设某个文件块里的一行文字是”Thisis a small cat. That is a smalldog.”,那
么,Map 过程会对这一行进行处理,将每个单词从句子解析出来,依次生成形如
<“this”,1>, <”is”, 1>, <”a”, 1>, <”small”, 1>,<”cat”, 1>, <”that”, 1>, <”
is”, 1>,<”a”, 1>, <”small”, 1>, <”dog”,1>的键值对,<”this”,1>表示“this”
这个单词出现了 1 次,在每个键值对里,单词出现的次数都是 1 次,允许有相同
的键值对多次出现,比如<”is”,1>这个键值对出现了 2 次。Reduce 过程就是合
并同类项,将上述产生的相同的键值对合并起来,将这些单词出现的次数累加起
来,计算结果就是<“this”,1>, <”is”, 2>, <”a”, 2>, <”small”, 2>,<”cat”,
1>, <”that”, 1>, <”dog”,1>。这种方式很简洁,并且可以进行多种形式的优化。
比如说,在一个机器上,对本地存储的 1G 的文件块先 Map,然后再 Reduce,那
么就得到了这 1G 的词频统计结果,然后再将这个结果传送到远程机器,跟其他
999 台机器的统计结果再次进行 Reduce,就得到 1000G 文件的全部词频统计结
果。如果文件没有那么大,只有三四个 G,就不需要在本地进行 Reduce 了,每
次 Map 之后直接将结果传送到远程机器做 Reduce
WordCount例子详细解析
package org.apache.hadoop.examples; import java.io.IOException;
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.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
/*
* @author: 1605-1
* @modify: 2019.9.3
* **/
public class WordCountTest {
//此阶段为分割数据 前两个泛型输入 后两个输出
public static class Map extends Mapper<Object , Text , Text , IntWritable>{
private static Text newKey=new Text();//新建输出为文本型输出 倒数第二个泛型
private static final IntWritable one = new IntWritable(1);
//第一个参数一般用不上 第二个参数为输入信息为文本 第三第四个参数 <”This”,1>
public void map(Object key,Text value,Mapper<Object, Text, Text, IntWritable>.Context context) throws IOException, InterruptedException{
String line=value.toString(); //读入数据
System.out.println(line);//输出数据到控制台
String[] array=line.split(" ");//把数据按照空格分割存为数组
for(int i=0;i<array.length;i++) {
System.out.println(array[i]+"----map");//调试输出分割后的每个单词
newKey.set(array[i]);//往输出流文本添加数据
context.write(newKey, one);
}
}
} //在reduce阶段,是map阶段分割后的经过排序后的数据向reduce任务中copy的过程,在此过程中会有一个背景线程将相同的key值进行合并,
//并将其value值归并到一个类似集合的容器中,此时的逻辑就是我们要遍历这个容器中的数据,计算它的值,然后输出
public static class Reduce extends Reducer<Text, IntWritable, Text, IntWritable>{
public void reduce(Text key,Iterable<IntWritable> values,Context context) throws IOException, InterruptedException{
int num=0;
//values <1><1,1>
//上面的key是上面的map传过来的 去重后的值应该是吧
int count=0;
for(IntWritable val:values){
count++;
} System.out.println("这是一个循环"+key);
context.write(key,new IntWritable(count));
}
} public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException{
System.setProperty("hadoop.home.dir", "D:\\Program Files\\windowshadoop\\hadoop-2.6.4");
Configuration conf=new Configuration();
Path in=new Path("hdfs://192.168.1.101:9000/KETANGCESHI/CESHI/in/wordcount.txt");
Path out=new Path("hdfs://192.168.1.101:9000/KETANGCESHI/CESHI/out/outp1");
Job job =new Job(conf,"OneSort");
FileInputFormat.addInputPath(job,in);
FileOutputFormat.setOutputPath(job,out);
job.setJarByClass(WordCountTest.class);
job.setMapperClass(WordCountTest.Map.class);
job.setReducerClass(WordCountTest.Reduce.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
job.waitForCompletion(true);
System.exit(job.waitForCompletion(true) ? 0 : 1); } }
个人不理解的详细解析
1 Text类从 hadoop 的 io 包里引入 Text 类。Text 类是存储字符串的可比较可序列化类(这个类用到很多个人感觉跟String 的区别为 这个可以序列化 至于序列化我也不知道是啥)
2 public class XXXX extends Mapper<Object, Text, Text,IntWritable>
这四个泛型参数是什么
这里,第一个参数类型是 Object ,表示
一般用不动 ,第二个参数参数类型是 Text,表示输入值的类型,第三
个参数类型也是 Text,表示输出键类型,第四个参数类型是 IntWritable,表示输
出值类型 (第一个好像不怎么用到 第二个是那个文本输入类型(你读入的文件) 第三第四个相当于 key 和value 了看你怎么用了)
第一个参数再次解释
第一个参数 Object 是 Hadoop 根据默认值生成的,一般是文件块
里的一行文字的行偏移数,这些偏移数不重要,在处理时候一般用不上,第二个
参数类型是要处理的字符串,形如”Thisis a cat.”。经过 Map 处理之后,输出
的就是诸如<”This”,1>的键值对,这个”This”就是第三个参数类型,是 Text
类型,而 1 就是第四个参数类型,是 IntWritable。
关于那个wordcount IntWritableone = new IntWritable(1) 为什么 后面参数一直是1呢 ?
这个1 就是发现一个单词计数一次 假如是2的话发现一个单词就计数两次就不准确了
Reducer 过程 大致解释
1 public class XXXX extends Reducer<Text,IntWritable,Text,IntWritable>
这个类继承 Hadoop 的 Reducer 类。
这里的”<Text,IntWritable,Text,IntWritable>”,含义跟上一节一样,依次分别是
输入键类型,输入值类型,输出键类型,输出值类型。
2 public void reduce(Text key, Iterable<IntWritable> values,Context context)
重载的这个函数
key 是输入键类型,values 是一个实现了 Iterable 接口的变量,
可以把它理解成 values 里包含若干个 IntWritable 整数,可以通过迭代的方式遍
历所有的值,至于 Context 类型,跟 Mapper 里的Context 类似的方式,是在 Redurer
类内部实现的。
举例来说,假如处理一个字符串”Thisis a That isa“,那么,经过 Map 过程之后,
到达 reduce 函数的时候,依次传递给 reduce 函数的是:key=”This”,values=<1>;
key= “is”,values=<1,1>;key = “a”,values=<1, 1>;key=”That”,values=<1>。
注意,在 key= “is”和 key=”a”的时候,values 里有两个 1
还有刚开始不懂得 那个map和reduce 相当于 读入一行 再操作(这个我没法说什么意思也许我不是这个意思 我这里输出了一下System.out.println("这是一个循环"+key); 自己理解一下吧)
后面main函数 解释
Configuration 类,顾名思义,读写和保存各种配置资源。
2)“import org.apache.hadoop.fs.Path”
引入 Path 类,Path 类保存文件或者目录的路径字符串。
3)“import org.apache.hadoop.mapreduce.Job”
引入 Job 类。在 hadoop 里,每个需要执行的任务是一个 Job,这个 Job 负责很多
事情,包括参数配置,设置 MapReduce 细节,提交到 Hadoop 集群,执行控制,
查询执行状态,等等。
4)”importorg.apache.hadoop.mapreduce.lib.input.FileInputFormat”
引入 FileInputFormat 类。这个类的很重要的作用就是将文件进行切分 split,因为
只有切分才可以并行处理。这个会在后面章节有详细解释。
5)“import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat”
引入 FileOutputFormat 类,处理结果写入输出文件。
6)“import org.apache.hadoop.util.GenericOptionsParser”
引入 GenericOptionsParser 类,这个类负责解析 hadoop 的命令行参数。
7)”publicclass WordCount ”
这是wordcount主类,它负责读取命令行参数,配置Job,调用Mapper和Reducer,
返回结果等等工作。
8)“Configurationconf = new Configuration()”
默认情况下,Configuration 开始实例化的时候,会从 Hadoop 的配置文件里读取
————————————— ————————————————
参数。
9)”String[]otherArgs = new GenericOptionsParser(conf, args).getRemainingArgs()”
读取参数分两步,上一步是从 Hadoop 的配置文件读取参数,这一步是从命令行
参数读取参数,args 是存放命令行参数的字符串数组。
10)“if (otherArgs.length != 2) ”
如果命令行参数不是 2 个,就出错了,退出。因为程序需要知道处理的是哪个输
入文件,处理结果放到哪个目录,必须是两个参数。
11)”Job job = new Job(conf, "wordcount")”
每个运行的处理任务就是一个 Job,”worodcount”是 Job 的名字。
12)“ job.setJarByClass(WordCount.class)”
Jar 文件是 Java 语言的一个功能,可以将所有的类文件打包成一个 Jar 文件,
setJarByClass 的意思是,根据 WordCount 类的位置设置 Jar 文件。
13)“job.setMapperClass(TokenizerMapper.class)”
设置 Mapper。
14)“job.setReducerClass(IntSumReducer.class)”
设置 Reducer。
15)“job.setOutputKeyClass(Text.class)”
设置输出键的类型。
16)“job.setOutputValueClass(IntWritable.class)”
设置输出值的类型。
17)“FileInputFormat.addInputPath(job, new Path(otherArgs[0]))”
设置要处理的文件,也就是输入文件,它是 otherArgs 的第一个参数。
18)“FileOutputFormat.setOutputPath(job, new Path(otherArgs[1]))”
设置输出文件,将处理结果写到这个文件里,它是 otherArgs 的第二个参数。
————————————— ————————————————
19)“System.exit(job.waitForCompletion(true) ? 0 : 1)”
最后一步,job 开始执行,等待执行结束。
hadoop 第一个 mapreduce 程序(对MapReduce的几种固定代码的理解)的更多相关文章
- HDFS设计思路,HDFS使用,查看集群状态,HDFS,HDFS上传文件,HDFS下载文件,yarn web管理界面信息查看,运行一个mapreduce程序,mapreduce的demo
26 集群使用初步 HDFS的设计思路 l 设计思想 分而治之:将大文件.大批量文件,分布式存放在大量服务器上,以便于采取分而治之的方式对海量数据进行运算分析: l 在大数据系统中作用: 为各类分布式 ...
- 如果公司里有上百个表要做触发器,如果手动写代码的话。很累,所以今天写了一个小程序,自动生成mysql的触发代码。
<?php $dbname = 'test';//数据库 $tab1 = 'user'; //执行的表 $tab2 = 'user_bak'; //被触发的表 $conn = mysql_con ...
- Hadoop学习之第一个MapReduce程序
期望 通过这个mapreduce程序了解mapreduce程序执行的流程,着重从程序解执行的打印信息中提炼出有用信息. 执行前 程序代码 程序代码基本上是<hadoop权威指南>上原封不动 ...
- 使用Playground编写第一个Swift程序
从控制台输出“HelloWorld”是我学习C语言的第一步,也是我人生中非常重要的一步.多年后的今天,我仍希望以HelloWorld作为第一步,与大家共同开启一个神奇.瑰丽的世界——Swift编程. ...
- MyBatis-02-第一个Mybatis程序
2.第一个Mybatis程序 思路:搭建环境-->导入Mybatis-->编写代码-->测试! 2.1.搭建环境 搭建数据库 CREATE DATABASE `mybatis`; u ...
- [刘阳Java]_第一个Java程序_第7讲
1. 其实第一个Java程序是很简单,但是当自己编写第一个Java程序时候需要注意如下几个内容: 理解Java程序的运行环境 校验你的Java环境变量是否能够运行你所写的第一个Java程序 理解Jav ...
- Hadoop学习历程(四、运行一个真正的MapReduce程序)
上次的程序只是操作文件系统,本次运行一个真正的MapReduce程序. 运行的是官方提供的例子程序wordcount,这个例子类似其他程序的hello world. 1. 首先确认启动的正常:运行 s ...
- 一起学Hadoop——使用IDEA编写第一个MapReduce程序(Java和Python)
上一篇我们学习了MapReduce的原理,今天我们使用代码来加深对MapReduce原理的理解. wordcount是Hadoop入门的经典例子,我们也不能免俗,也使用这个例子作为学习Hadoop的第 ...
- hadoop安装后运行一个单实例(测试MapReduce程序)
1.安装hadoop 解压hadoop-1.2.1-bin.tar.gz包 tar -zxvf hadoop-1.2.1-bin.tar.gz /opt/modules/ 解压后在/opt/mo ...
随机推荐
- 显ipQQ
链接:https://pan.baidu.com/s/1l1WN4b3jT8n4e66DH8d-cg 提取码:kjm4
- xadmin 后台管理
xadmin后台管理 安装:luffy虚拟环境下 >: pip install https://codeload.github.com/sshwsfc/xadmin/zip/django2 注册 ...
- C++11特性中的to_string
写在最前面,本文摘录于柳神笔记 to_string 的头⽂件是 #include , to_string 最常⽤的就是把⼀个 int 型变量或者⼀个数字转化 为 string 类型的变量,当然也可以转 ...
- proto school tutorial: blog: lesson 1
https://proto.school/#/blog/01 我们现在希望:把一个post 和他的作者联系起来. 从之前的教程here中,你可以知道, 一个cid 就是代表一个link 比如: { l ...
- Jmeter 如何发起一个post请求
举例平台:https://www.juhe.cn/docs/api/id/65 前提条件: 1)要在聚合网站注册实名认证才可以收到Key,用于Get请求的参数数值 2)Jmeter本地安装好 3.这是 ...
- Codeforces Round #588 (Div. 2)E(DFS,思维,__gcd,树)
#define HAVE_STRUCT_TIMESPEC#include<bits/stdc++.h>using namespace std;long long a[100007];vec ...
- 解Bug之路-记一次调用外网服务概率性失败问题的排查
前言 和外部联调一直是令人困扰的问题,尤其是一些基础环境配置导致的问题.笔者在一次偶然情况下解决了一个调用外网服务概率性失败的问题.在此将排查过程发出来,希望读者遇到此问题的时候,能够知道如何入手. ...
- php 随机生成汉字
function getChar($num) // $num为生成汉字的数量 { $b = ''; for ($i=0; $i<$num; $i++) { // 使用chr()函数拼接双字节汉字 ...
- iOS中常用的手势
--前言 智能手机问世后的很长一段时间,各大手机厂商都在思考着智能手机应该怎么玩?也都在尝试着制定自己的一套操作方式.直到2007年乔布斯发布了iPhone手机,人们才认识到智能手机就应该这样玩. 真 ...
- ElementUI 删除 el-table 当前选中行(不是selection列)
一句话即可: this.表格绑定的data.splice(this.$refs.表格的ref.store.states.selection, 1)