内容简介:原文地址:MapReduce是一种编程模型,"Map(映射)"和"Reduce(归约)",是它们的主要思想,我们通过Map函数来分布式处理输入数据,然后通过Reduce汇总结果并输出。其实这个概念有点类似于我们Java8中的StreamApi,有兴趣的同学也可以去看看。MapReduce任务过程分为两个处理阶段,map阶段和reduce阶段。每个阶段都以键-值对作为输入输出,键和值的类型由我们自己指定。通常情况map的输入内容键是LongWritable类型,为某一行起始位置相对于文件起始位置的偏移量;值
原文地址: itweknow.cn/detail?id=6… ,欢迎大家访问。
MapReduce是一种编程模型,"Map(映射)"和"Reduce(归约)",是它们的主要思想,我们通过Map函数来分布式处理输入数据,然后通过Reduce汇总结果并输出。其实这个概念有点类似于我们 Java 8中的StreamApi,有兴趣的同学也可以去看看。
MapReduce任务过程分为两个处理阶段,map阶段和reduce阶段。每个阶段都以键-值对作为输入输出,键和值的类型由我们自己指定。通常情况map的输入内容键是LongWritable类型,为某一行起始位置相对于文件起始位置的偏移量;值是Text类型,为该行的文本内容。
前提条件
- 一个maven项目。
- 一台运行着hadoop的 linux 机器或者虚拟机,当然了hadoop集群也可以,如果你还没有的话可以戳这里。
我们编写一个MapReduce程序的一般步骤是:(1)map程序。(2)reduce程序。(3)程序驱动。下面我们就根据这个顺序来写一个简单的示例,这个例子是用来统计文件中每个字符出现的次数并输出。
项目依赖
我们先来解决一下依赖问题,在 pom.xml
中添加如下内容。
<dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-client</artifactId> <version>${hadoop.version}</version> </dependency> 复制代码
Map程序
我们继承 Mapper
类并重写了其map方法。Map阶段输入的数据是从hdfs中拿到的原数据,输入的key为某一行起始位置相对于文件起始位置的偏移量,value为该行的文本。输出的内容同样也为键-值对,这个时候输出数据的键值对的类型可以自己指定,在本例中key是Text类型的,value是LongWritable类型的。输出的结果将会被发送到reduce函数进一步处理。
public class CharCountMapper extends Mapper<LongWritable, Text, Text, LongWritable> { @Override protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException { // 将这一行文本转为字符数组 char[] chars = value.toString().toCharArray(); for (char c : chars) { // 某个字符出现一次,便输出其出现1次。 context.write(new Text(c + ""), new LongWritable(1)); } } } 复制代码
Reduce程序
我们继承 Reducer
类并重写了其reduce方法。在本例中Reduce阶段的输入是Map阶段的输出,输出的结果可以作为最终的输出结果。相信你也注意到了,reduce方法的第二个参数是一个Iterable,MapReduce会将map阶段中相同字符的输出汇总到一起作为reduce的输入。
public class CharCountReducer extends Reducer<Text, LongWritable, Text, LongWritable> { @Override protected void reduce(Text key, Iterable<LongWritable> values, Context context) throws IOException, InterruptedException { long count = 0; for (LongWritable value : values) { count += value.get(); } context.write(key, new LongWritable(count)); } } 复制代码
驱动程序
到目前为止,我们已经有了map程序和reduce程序,我们还需要一个驱动程序来运行整个作业。可以看到我们在这里初始化了一个Job对象。Job对象指定整个MapReduce作业的执行规范。我们用它来控制整个作业的运作,在这里我们指定了jar包位置还有我们的 Map
程序、 Reduce
程序、 Map
程序的输出类型、整个作业的输出类型还有输入输出文件的地址。
public class CharCountDriver { public static void main(String[] args) throws Exception { Configuration configuration = new Configuration(); Job job = Job.getInstance(configuration); // Hadoop会自动根据驱动程序的类路径来扫描该作业的Jar包。 job.setJarByClass(cn.itweknow.mr.CharCountDriver.class); // 指定mapper job.setMapperClass(CharCountMapper.class); // 指定reducer job.setReducerClass(CharCountReducer.class); // map程序的输出键-值对类型 job.setMapOutputKeyClass(Text.class); job.setMapOutputValueClass(LongWritable.class); // 输出键-值对类型 job.setOutputKeyClass(Text.class); job.setOutputValueClass(LongWritable.class); // 输入文件的路径 FileInputFormat.setInputPaths(job, new Path(args[0])); // 输入文件路径 FileOutputFormat.setOutputPath(job, new Path(args[1])); boolean res = job.waitForCompletion(true); System.exit(res?0:1); } } 复制代码
你会发现我们初始化了一个空的Configuration,但是并没有进行任何的配置,其实当我们将其运行在一个运行着hadoop的机器上时,它会默认使用我们机器上的配置。在后续的文章中我也会写一下如何在程序中进行配置。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 「Flask实战」鱼书项目实战一
- 「Flask实战」鱼书项目实战三
- 「Flask实战」鱼书项目实战四
- 「Flask实战」鱼书项目实战六
- RocketMQ实战系列从理论到实战
- 「Flask实战」flask鱼书项目实战二
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
The Nature of Code
Daniel Shiffman / The Nature of Code / 2012-12-13 / GBP 19.95
How can we capture the unpredictable evolutionary and emergent properties of nature in software? How can understanding the mathematical principles behind our physical world help us to create digital w......一起来看看 《The Nature of Code》 这本书的介绍吧!