由TextInputFormat编译错误到Hadoop.mapred包和Hadoop.mapreduce包的区别

来源:互联网 发布:星际争霸1数据 编辑:程序博客网 时间:2024/04/29 01:34

今天看了Hadoop的InputSplits以后试着在自己写的MapReduce程序上使用TextInputFormat类(我使用的版本是Hadoop2.7.3,当前稳定版本),然而在main函数中调用此类时:

Job job = Job.getInstance(conf, "word count");job.setInputFormatClass(TextInputFormat.class);

一直报编译错误:The method setInputFormatClass(Class<? extends InputFormat>) in the type Job is not applicable for the arguments(Class<TextInputFormat>)

我一开始很懵,因为TextInputFormat本身是FileInputFormat的子类,而FileInputFormat继承InputFormat,所以TextInputFormat也应当继承InputFormat啊。赶紧去看源代码,结果和我想得也一样,我甚至一度怀疑我学到的java知识都是假的。。

后来脑子里闪过一个念头,难道因为我的TextInputFormat是假的?马上一查,果然有两个TextInputFormat类,我用的是在org.apache.hadoop.mapred包中,而Job类期望的类是在org.apache.hadoop.mapreduce.lib.input包中。

本来这种事情碰到的也挺多了。。但是花了一上午才解决,总要把这两个包的区别弄个明白。先读两个包中的源码,发现除了实现有略微区别,大体上是差不多的(其实并没有太看懂(╯‵□′)╯︵┻━┻ )于是借助搜索引擎,才明白hadoop.mapred包是旧API,而hadoop.mapreduce包是新API,新API是在0.20版本加入的(所以过了这么久为什么不把旧API删掉呢!)

Hadoop新旧API的区别

那新API相比旧API有哪些改动呢?这些改动又有哪些影响呢?下面的内容主要来自Hadoop: The Definitive Guide 4th Edition,加上了一些我个人的理解。

  1. 新API将一些接口改为抽象类。因为相比于接口,抽象类在继承时可以在不改变默认实现的情况下使用新的方法,增加了一些灵活性和兼容性。目前已知的被改变的类包括:Mapper, Reducer, Partitioner, InputFormat, OutputFormat, InputSplit, RecordReader, RecordWriter
  2. 新API引入了Context类。Context类是包含了许多系统变量和参数的封装,这样用户可以在编写MapReduce程序时方便的与系统直接交流,大大拓宽了编程思路
  3. 新API在MapperReducer两个抽象类中添加了run() 函数,使得用户能直接通过重写此函数来控制运行流程。旧API中的MapRunnable接口可以实现这一点,但是Reducer中无法实现。
  4. Job类代替了JobClient类来实现对新改动的操作。这也是我出现的问题的根本原因,因为我用的新API的Job类,当然无法调用旧API的InputFormat
  5. 新API将旧API中的JobConf类中的内容移到了它的父类Configuration类中,并且能通过新的Job类中的一些helper method来使用。换句话说就是将Configuration类的功能也集成到Job类中了。
  6. 新API的输出文件命名将map输出和reduce输出分开,分别是part-m-nnnnn和part-r-nnnn,而旧API中两者均被命名为part-nnnnn
  7. 新API中用户重写的方法现在会被声明抛出Java.lang.InterruptedException。这样用户就可以有意在程序中抛出异常来实现对终止长时间运行的程序之类的操作。
  8. 新API中reduce()函数现在传入值的结构为java.lang.Iterable而不是旧API中的java.lang.Iterator(在java7中已经被移到java.util包中)。这样可以使reduce中的迭代操作变得更容易。
原创粉丝点击