此常规Java项目,不是Maven项目,也不是Java Enterprise项目。html
打开 File->New->Project菜单,选择Java便可,逐步点击Next,在目录D:\Java\hadoop\mr下建立一个项目名称。java
这里咱们建立的项目叫groupbysum,表示groupbysum MapReduce小项目。apache
之后各类功能的mapreduce程序均已小项目形式放在mr目录下。数组
其实咱们也能够把mr建立为一个项目(相似空间),各个小mapreduce程序做为modules(项目)放在该项目(空间)下,但这种方式通常是是大项目,分组协同开发各个模块功能的时候使用较多,这里就不采用了,一次只开发一个项目。网络
导入执行mapreduce程序依赖的Hadoop包:app
Apache Commons IO : 主要是文件处理,好比复制、输入输出、文件名处理、大小写敏感等等。框架
The Apache Commons IO library contains utility classes, stream implementations, file filters, file comparators, endian transformation classes, and much more. 函数
导入操做:打开项目结构(CTRL+ALT_SHIFT+S 或者使用工具栏的 图标 ),点击Modules,切换tab标签到Dependencies,点击 + 加号,选择准备好的包含这些Jar包的目录D:\Java\hadoop\jar,到这里功能上已经能够用了,可是为了便于区分管理咱们导入的Jar包,这里能够点击这个目录,选择右侧的小铅笔(EDIT),给这些包在这个项目里起一个分组名称,这里咱们起了hadoop-2.7.6。工具
写Java类,一般有两种方式,一种是类中类,只写一个Java文件,一种是一个类一个Java文件,多个Java文件。oop
这里咱们选择分开写,增长对mapreduce原理对认识和理解。
建立包体,右击src,new->package,输入包名,这里咱们命名包为com.leeyk99.com。(这个包名写的瞎眼了,后续会写com.leeyk99.hadoop)
重点参考:
https://www.cnblogs.com/bovenson/p/6275762.html?utm_source=itdadao&utm_medium=referral
我的学习的Java代码(文件和目录io代码 ioReadWrite.java)
意外发现:
由于以前在公司经过Maven建立了WordCount官方示例MR项目,仅在pom.xml中配置了最重要的几个Hadoop jar包依赖,成功运行。实际上Maven项目自动下载了相关的jar包,好比jackson-core-asl-1.9.13.jar、commons-configuration-1.10.ja等。
<!-- 基础依赖hadoop-core和hadoop-common --> <!--hadoop-core的version通常为1.2.1--> <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-core</artifactId> <version>1.2.1</version> </dependency> <!--hadoop-common的version能够依照你的实际须要来--> <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-common</artifactId> <version>2.7.6</version> </dependency> <!--若是须要读写HDFS,则还须要依赖hadoop-hdfs和hadoop-client--> <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-hdfs</artifactId> <version>2.7.6</version> </dependency> <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-client</artifactId> <version>2.7.6</version> </dependency>
在这个普通Java项目导入第2步指定的jar包,报告了不少类缺失错误,最后都一一找来了。故,实际依赖完整的Jar包以下:
导入这些包后,运行无误。
故,在对Hadoop的包的功能基本了解或者实际开发的时候,为提升效率,可使用Maven项目。
本次Hadoop MR学习总结,主要集中在对总体运行逻辑和局部编写细节的学习和测试,源码原理未研究。
该MR程序测试了单度量在单维度上聚合统计的情形,即经常使用的:
select dim_a,sum(kpi_a) from table_name group by dim_a
GroupBySumMapper类继承抽象类:org.apache.hadoop.mapreduce.Mapper (新API)。(旧API:extends MapReduceBase implements Mapper<LongWritable, Text, Text, DoubleWritable>)
Mapper是一个泛型类型,有四个形参,分别是map函数的输入键、输入值、输出键、输出值。泛型类型的形参只能是引用类型,不能是原始类型(如int、double、char)。
Hadoop提供了一套可优化网络序列化传输的引用类型(LongWritable、Text、DoubleWritable、IntWritable),而不是直接用Java的引用类型(Long、String、Double、Integer,被hadoop提供的四个类型替代).
map函数是对一行记录进行处理,数据集的每一行是输入,输入键就是相对于文件起始位置的偏移量(若是从第一行开始,就是行号了),由于Hadoop一般是处理大数据量,所以输入键类型一般指定为 LongWritable.
获取到一行记录后,将行转换成成Java的String类型,提取相应的数据域(列),经常使用的方法:
获取到指定数据域后,conntext.write将结果输出,写出到临时文件,做为reduce函数的输入。
map任务将其输出写到本地硬盘,而非HDFS。由于map的输出只是中间结果,一旦做业完成,map的输出便可以删除,存储到HDFS并实现备份,不免小题大作(说白了,占用存储,数据备份也须要时间和带宽)。
reduce函数以map的输出做为输入,所以reduce函数的输入键、输入值和map的输出键、输出值类型须要是一致的,这种状况下reduce函数的输出类型也必须是Text和DoubleWritable。
reduce函数实现的操做一般是对输入值的遍历处理,好比求和、计数、比较、取均、去重等多种运算,而后将结果输出,写入到HDFS,做为最终产出结果。
Job对象指定做业执行规范。能够将代码打包成Jar文件,发不到Hadoop集群。没必要指明JAR文件名称,在Job对象的setJarByClass(GroupBySumRun.class)方法中传递类便可。Hadoop会根据这个类查找相关的JAR文件.
构造Job对象后,指定输入(调用FileInputFormat类的静态方法addInputPath(),能够屡次调用实现多路径输入,路径能够是单个文件、一个目录、符合特定模式的一些列文件)、输出(调用FileOutputFormat类的静态方法setOutputPath(),只能一个,且在运行前不能存在)路径。
接着setMapperClass、setReducerClass指定要使用的map类型、reduce类型。至于setCombinerClass根据须要来使用。combiner是对map的输出在MR框架混洗后的分组结果,进行组内计算,减小须要传递给reduce函数的数据量。
setOutputKeyClass()、setOutputValueClass()控制reduce函数的输出类型,而且必须和Reduce类产生的相匹配,map函数的输出类型默认状况下和reduce函数是相同的,所以mapper产生出和reducer函数相同的类型时,不须要单独设置map的输出类型,不然须要经过setMapOutputKeyClass()、setMapOutputValueClass()方法来设置map函数的输出类型。
文件的输入输出:
输入的类型经过输入格式来控制,setInputFormatClass(),若是不指定,则使用默认的格式TextInputFormat.class(文本输入格式);
输出的类型经过输出格式来控制,setOutputFormatClass(),若是不指定,则使用默认的格式TextOutputFormat.class(文本输入格式).
设置完成后,能够开始运行做业。waitForCompletion()方法提交做业并等待执行完成。其参数true表示做业会把其进度信息写到控制台,返回结果是布尔值,true-成,false-败。
这个例子的代码不是最简洁的,后续参照《Hadoo权威指南》再写个 简洁点的。
因为reduce函数的输出目录在运行前必须不存在,为方便调试代码,不用每次都去手动删目录,写了DelOutputDir类,在提交做业前执行删除output目录及其目录下文件的方法。
这个方法要求output目录里只有文件,不能有目录,由于代码未对子目录做处理。
使用Intellij IDEA建立一个常规Java项目,导入外部依赖。参见一、2步。
这里未使用导入libraries的方法(这个是最推荐的方法,建立lib目录,添加JAR文件,后续尝试)。
Inerllij IDEA将程序打包成JAR文件,主要是作两件事:1.建立MANIFEST.MF文件,这个文件指定MAIN CLASS的位置(包);2.将MANIFEST.MF和编译后的class文件一块儿打包。
打开IDEA的项目结构 (CTRL+SHILT+ALT+S 或者 快捷图标 ),在Artifacts菜单中新建一个空JAR文件,若是有就进行配置便可。流程步骤:(未完待续)
6.代码、JAR包、测试数据下载
https://files.cnblogs.com/files/leeyuki/code.rar 代码
JAR包大于10M,博客园传不了,如须要自行下载或留言索取。