Java 实现MapReduce函数
明白了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函数的更多相关文章
- 简单的java Hadoop MapReduce程序(计算平均成绩)从打包到提交及运行
[TOC] 简单的java Hadoop MapReduce程序(计算平均成绩)从打包到提交及运行 程序源码 import java.io.IOException; import java.util. ...
- java String.split()函数的用法分析
java String.split()函数的用法分析 栏目:Java基础 作者:admin 日期:2015-04-06 评论:0 点击: 3,195 次 在java.lang包中有String.spl ...
- Android使用JNI(从java调用本地函数)
当编写一个混合有本地C代码和Java的应用程序时,需要使用Java本地接口(JNI)作为连接桥梁.JNI作为一个软件层和API,允许使用本地代码调用Java对象的方法,同时也允许在Java方法中调用本 ...
- 关于C++与Java中虚函数问题的读书笔记
之前一直用C++编程,对虚函数还是一些较为肤浅的理解.可近期由于某些原因搞了下Java,发现有些知识点不熟,于是站在先驱巨人的肩上谈谈C++与Java中虚函数问题. Java中的虚函数 以下是段别人的 ...
- 用JAVA写一个函数,功能例如以下: 随意给定一组数, 找出随意数相加之后的结果为35(随意设定)的情况
用JAVA写一个函数.功能例如以下:随意给定一组数,比如{12,60,-8,99,15,35,17,18},找出随意数相加之后的结果为35(随意设定)的情况. 能够递归算法来解: package te ...
- java中main函数解析(转载)
从写java至今,写的最多的可能就是主函数 public static void main(String[] args) {} 但是以前一直都没有问自己,为什么要这么写,因为在c语言中就没有这样子的要 ...
- java的数学函数总结
java的数学函数都放在java.lang这个包中,并且这些函数的方法在类Math中是作为static方法出现的,所以要引用一个特定的函数,只需将类Math和一个圆点写在要使用的方法前就好.如方法sq ...
- JAVA中字符串函数subString的用法小结
本篇文章主要是对JAVA中字符串函数subString的用法进行了详细的介绍,需要的朋友可以过来参考下,希望对大家有所帮助 String str; str=str.substring(int begi ...
- Java中的函数对象
初次听说java中的函数对象可能,比较的陌生.可以类比着来理解一下,人们常说java中没有了指针,殊不知,java中的对象引用就是指针,有时候我们说一个对象往往指的就是这个对象的引用,也就是说基本上把 ...
随机推荐
- java-数字类
浏览以下内容前,请点击并阅读 声明 对于6种基本的数字类型,java提供了相对应的类.Number类和六种细分的子类.
- XIII Open Cup named after E.V. Pankratiev. GP of Azov Sea
A. Freestyle 如果逆序对为$0$,那么先手必败. 因为每次只能翻转长度为$4k+2$和$4k+3$的区间,所以每次操作之后逆序对的奇偶性一定会发生改变. 因此如果逆序对个数为偶数,则先手必 ...
- 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树
[BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...
- Android 蓝牙4.0 BLE
Android ble (Bluetooth Low Energy) 蓝牙4.0,也就是说API level >= 18,且支持蓝牙4.0的手机才可以使用. BLE是蓝牙4.0的核心Profil ...
- 巧用translate设置元素垂直水平居中
之前在做手机项目时,用到很多自定义弹窗,然后要求都垂直水平要居中,最开始的时候想用calc来计算,可是css3 的calc兼容性不是很好,于是后来就借助了js来计算, 今天偶然看到别人的一个方法,瞬间 ...
- [深入浅出Windows 10]布局原理
5.2 布局原理 很多时候在编写程序界面的时候都会忽略了应用布局的重要性,仅仅只是把布局看作是对UI元素的排列,只要能实现布局的效果就可以了,但是在实际的产品开发中这是远远不够的,你可能面临要实现的布 ...
- spring源码学习之路---深度分析IOC容器初始化过程(四)
作者:zuoxiaolong8810(左潇龙),转载请注明出处,特别说明:本博文来自博主原博客,为保证新博客中博文的完整性,特复制到此留存,如需转载请注明新博客地址即可. 最近由于工作和生活,学习耽搁 ...
- Linux多线程实例练习 - pthread_create()
Linux多线程实例练习 pthread_create():创建一个线程 int pthread_create(pthread_t *tidp, const pthread_attr_t *attr, ...
- python 之Twsited
Twisted是一个事件驱动的网络框架,其中包含了诸多功能,例如网络协议,线程,数据库管理,网络操作,电子邮件等 事件驱动 一,注册事件 二,触发事件 自定义事件框架 event_fram.py # ...
- JavaScript声明全局变量的三种方式
JavaScript声明全局变量的三种方式 JS中声明全局变量主要分为显式声明或者隐式声明下面分别介绍. 声明方式一: 使用var(关键字)+变量名(标识符)的方式在function外部声明,即为 ...