明白了MapReduce程序的工作原理之后,下一步就是写代码来实现它。我们需要三样东西:一个map函数、一个reduce函数和一些用来运行作业的代码。map函数由Mapper类来表示,后者声明一个map()虚方法。范例2-3显示了我们的map函数实现。

范例2-3 查找最高气温的Mapper类

Import java.Io.IOException;
import org.apahce.hadoop.io.IntWritable;
import org.apahce.hadoop.io.LongWritable;
import org.apahce.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper; public class MaxTemperatureMapper extends MapReduceBase implements Mapper<LongWritable,Text,Text,IntWritable>{ private static final int MISSING = 9999; @Override
public void map(LongWritable key,Text value,Context context) throws IOException,InterruptedException{
String line = value.toString();
String year = line.substring(15,19);
int airTemperature; if(line.charAt(87) =='+'){
airTemperature = Integer.parseInt(line.substring(88,92));
else{
airTemperature = Integer.parseInt(line.subtring(87,92));
}
String quality = line.substring(92,93);
if(airTemperature != MISSING &&quality.matches("[01459]")){
context.write(new Text(year),new IntWritetable(airTemperature));
} } } }

这个Mapper类是一个泛型类型,他有四个行参类型,分别指定:map函数的输入键,输入值,输出键和输出值的类型。就现在的例子来说,输入键是一个长整数偏移量,输入值是一行文本,输出键是年份,输出值是气温(整数)。Hadoop本身提供了一套可优化网络序列化传输的基本类型,而不直接使用Java内嵌的类型。这些类型都在org.apache.hadoop.io包中。这里使用LongWritable类型(相当于Java的Long类型)、Text类型(相当于Java的String类型)和IntWritable类型(相当于Java的Integer类型)。

map()方法的输入时一个键和一个值。我们首先将包含有一行输入的Text值转换成Java的String类型,之后使用substring()方法提取我们感兴趣的列。

map()方法还提供了Context实例用于输出内容的写入。在这种情况下,我们将年份按Text对象进行读/写(因为我们把年份当作键),将气温值封装在IntWritable类型中。只有气温数据不缺并且对应质量代码显示为正确的气温读数时,这些数据才会被写入输出记录中。

以类似方法用Reducer来定义reduce函数,如范例2-4所示。

范例2-4.查找最高气温的Reducer类

import  java.io.IOException;
import org.apache.hadoop.io.IntWritable;
import org.apche.hadoop.io.Text;
import org.apche.hadoop.mapreduce.Reducer; public class MaxTemperatureReducer extends Reducer<Text,IntWritable,Text,IntWritable>{ @Overide public void reduce(Text key,Interable<IntWritable> values,Context context){
int maxValue = Integer.MIN_VALUE;
for(IntWritable value:values){
maxValue = Max.max(maxValue,value.get());
}
context.write(key,new IntWritable(maxValue)); } }

同样,reduce函数也有四个形式参数类型用于指定输入和输出类型。reduce函数的输入类型必须匹配map函数的输出类型:即Text类型和IntWritable类型。在这种情况下,reduce函数的输出类型也必须是Text和IntWritable类型,分别输出年份及其最高气温。这个最高气温是通过循环比较每个气温与当前所知最高气温所得到的。

第三部分代码负责运行MapReduce作业(请参见范例2-5)

范例2-5 这个应用程序在气象数据集中找出最高气温

import java.oo.IOException;
import org.apache.hadoop.fs.Path;
import org.apahce.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.input.FileOutputFormat;
import org.apache.hadoop.mapreduce.input.FileOutputFormat; public class MaxTemperature{ public static void main(String[] args) throws Exception{ if(args.length !=2){
System.err.printlin("Usage:MaxTemperature<input path> <output path>");
System.exit(-1); } Job job = new Job();
job.serJarByClass(MaxTemperature.class);
job.setName("Max temperature"); FileInputFormat.addInputPath(job,new Path(args[0]));
FileOutputFormat.setOutputPath(job,new Path([args[1])); job.setMapperClass(MaxTemperatureMapper,class);
job.setReducerClass(MaxTemperatureReducer.class); job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class); System.exit(job.waitForCompletion(true)?0:1); } }

Job对象可以指定作业执行规范。我们可以用它来控制整个作业的运行。我们在Hadoop集群上运行这个作业时,要把代码打包成一个Jar文件(Haoop在集群上发布在合格文件)。

不必明确指定JAR文件的名称,在Job对象的setJarByClass()方法中传递一个类即可,Hadoop利用这个类来查找包含它的JAR文件,进而找到相关的Jar文件。

构造Job对象之后,需要指定输入和输出数据的路径。调用FileInputFormat类的静态方法addInputPath()来定义输入数据的路径,这个路径可以是单个的文件、一个目录(此时,将目录下所有文件当做输入)或符合特定文件模式的一系列文件。由函数名可知,可以多次调用addInputPath()来实现多路径的输入。

调用FileOutputFormat类中的静态方法setOutputPath()来指定输出路径(只能有一个输出路径)。这个方法指定的是reduce函数输出文件的写入目录。在运行作业前该目录是不应该存在的,否则Hadoop会报错并拒绝运行作业。这种预防措施的目的是放置数据丢失(长时间运行的作业如果结果被意外覆盖,肯定是非常恼人的)。

接着,调用setMapperClas()和setReducerClass()指定map类型和reduce类型。
setOutputKeyClass()和setOutputValueClass()控制map和reduce函数的输出类型,正如本例所示,这两个输出类型一般都是相同的。如果不同,则通过setMapOutputKeyClass()和setMapOutputValueClass()来设置mao函数的输出类型。

输入的类型通过InputFormat类来控制,我们的例子中没有设置,因为使用的是默认的TextInputFormat(文本输入格式)。

在设置定义map和reduce函数的类之后,可以开始运行作业。Job中的waitForCompletion()方法提交作业并等待执行完成。该方法中的布尔参数是个详细标识,所以作业会把进度写到控制台。

waitForCompletion()方法返回一个布尔值,表示执行的成(true)败(false)。

Java 实现MapReduce函数的更多相关文章

  1. 简单的java Hadoop MapReduce程序(计算平均成绩)从打包到提交及运行

    [TOC] 简单的java Hadoop MapReduce程序(计算平均成绩)从打包到提交及运行 程序源码 import java.io.IOException; import java.util. ...

  2. java String.split()函数的用法分析

    java String.split()函数的用法分析 栏目:Java基础 作者:admin 日期:2015-04-06 评论:0 点击: 3,195 次 在java.lang包中有String.spl ...

  3. Android使用JNI(从java调用本地函数)

    当编写一个混合有本地C代码和Java的应用程序时,需要使用Java本地接口(JNI)作为连接桥梁.JNI作为一个软件层和API,允许使用本地代码调用Java对象的方法,同时也允许在Java方法中调用本 ...

  4. 关于C++与Java中虚函数问题的读书笔记

    之前一直用C++编程,对虚函数还是一些较为肤浅的理解.可近期由于某些原因搞了下Java,发现有些知识点不熟,于是站在先驱巨人的肩上谈谈C++与Java中虚函数问题. Java中的虚函数 以下是段别人的 ...

  5. 用JAVA写一个函数,功能例如以下: 随意给定一组数, 找出随意数相加之后的结果为35(随意设定)的情况

    用JAVA写一个函数.功能例如以下:随意给定一组数,比如{12,60,-8,99,15,35,17,18},找出随意数相加之后的结果为35(随意设定)的情况. 能够递归算法来解: package te ...

  6. java中main函数解析(转载)

    从写java至今,写的最多的可能就是主函数 public static void main(String[] args) {} 但是以前一直都没有问自己,为什么要这么写,因为在c语言中就没有这样子的要 ...

  7. java的数学函数总结

    java的数学函数都放在java.lang这个包中,并且这些函数的方法在类Math中是作为static方法出现的,所以要引用一个特定的函数,只需将类Math和一个圆点写在要使用的方法前就好.如方法sq ...

  8. JAVA中字符串函数subString的用法小结

    本篇文章主要是对JAVA中字符串函数subString的用法进行了详细的介绍,需要的朋友可以过来参考下,希望对大家有所帮助 String str; str=str.substring(int begi ...

  9. Java中的函数对象

    初次听说java中的函数对象可能,比较的陌生.可以类比着来理解一下,人们常说java中没有了指针,殊不知,java中的对象引用就是指针,有时候我们说一个对象往往指的就是这个对象的引用,也就是说基本上把 ...

随机推荐

  1. applet示例 WelcomeApplet.java <Core Java>

    import java.awt.BorderLayout; import java.awt.EventQueue; import java.awt.Font; import java.awt.Grap ...

  2. while的使用

    我在用while的时候, while(当这个对象的首个字是汉字){ 执行语句 } 我发现出现死循环的现象 其实我要再添加一个条件,就是不管是不是上述条件都成立,最终还是要结束的.

  3. Tomcat在局域网中localhost可以访问,但是无法通过本地ip访问,127.0.0.1也无法访问问题的解决方法

    环境:Tomcat6,Windows Server2008 R2, Tomcat使用默认端口8080. 在BO服务器上使用Tomcat6作为WEB服务器,在服务器本地使用http://localhos ...

  4. Excel: 公式

    单元格内输入  = xx公式 e.g  =EXACT(C2,D2)   //比较两个单元格内的文本是否相同

  5. unity 常用函数

    GameObject.FindGameObjectByTag(); anim.SetFloat("speed",Mathf.Abs(h)); Physics2D.lineCast2 ...

  6. BZOJ 3110 k大数查询 & 树套树

    题意: 有n个位置,每个位置可以看做一个集合,现在要求你实现一个数据结构支持以下功能: 1:在a-b的集合中插入一个数 2:询问a-b集合中所有元素的第k大. SOL: 调得火大! 李建说数据结构题能 ...

  7. ACM 兄弟郊游问题

    兄弟郊游问题 时间限制:3000 ms  |  内存限制:65535 KB 难度:2   描述 兄弟俩骑车郊游,弟弟先出发,每分钟X米,M分钟后,哥哥带一条狗出发.以每分钟Y米的速度去追弟弟,而狗则以 ...

  8. 【BZOJ】1106: [POI2007]立方体大作战tet

    题意 给定一个长度为\(2n(1 \le n \le 500000)\)的序列,\(1\)~\(n\)各出现两次,可以交换相邻两项,两个同样的数放在一起会对消,求把所有数对消的最小交换次数. 分析 如 ...

  9. Emmet:HTML/CSS代码快速编写神器

    本文来源:http://www.iteye.com/news/27580    ,还可参考:http://www.w3cplus.com/tools/emmet-cheat-sheet.html Em ...

  10. mysql配置之skip-external-locking

    转载:http://www.kuqin.com/database/20120815/328905.html MySQL的配置文件my.cnf中默认存在一行skip-external-locking的参 ...