今天寫了段代碼突然發現,很多類在mapred和mapreduce中分別都有定義,下面是小菜寫的一段代碼:
public class MyJob extends Configured implements Tool
{
public static class MapClass extends MapReduceBase implements Mapper<Text, Text, Text, Text>
{//
public void map(Text key, Text value, OutputCollector<Text, Text> output, Reporter reporter) throws IOException
{
output.collect(value, key);
}
}
public static class Reduce extends MapReduceBase implements Reducer<Text, Text, Text, Text>
{
@Override
public void reduce(Text key, Iterator<Text> values, OutputCollector<Text, Text> output, Reporter reporter) throws IOException
{
String csv = "";
while (values.hasNext())
{
csv += csv.length() > 0 ? "," : "";
csv += values.next().toString();
}
output.collect(key, new Text(csv));
}
}
@Override
public int run(String[] args) throws Exception
{
Configuration conf = getConf();
JobConf job = new JobConf(conf, MyJob.class); //JobConf job = new JobConf(conf, MyJob.class);
Path in = new Path(args[0]);
Path out = new Path(args[1]);
FileInputFormat.setInputPaths(job, in);
FileOutputFormat.setOutputPath(job, out);
job.setJobName("MyJob");
job.setMapperClass(MapClass.class);
job.setReducerClass(Reduce.class);
job.setInputFormat(KeyValueTextInputFormat.class);
job.setOutputFormat(TextOutputFormat.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(Text.class);
job.set("key.value.separator.in.input.line", ",");
JobClient.runJob(job);
return 0;
}
public static void main(String[] args) throws Exception
{
// TODO Auto-generated method stub
int res = ToolRunner.run(new Configuration(), new MyJob(), args);
System.exit(res);
}
}
主要看run方法:
上面代碼中的Jobconf無可厚非,只有在mapred包中有定義,這個沒問題。
但是FileInputFormat和FileOutputFormat在mapred和mapreduce中都有定義,剛開始腦海里對這些都沒有概念,就引用了mapreduce中的FileInputFormat和FIleOutputFormat。
這樣操作就帶來了后面的問題
FileInputFormat.setInputPaths(job, in);
FileOutputFormat.setOutputPath(job, out);
這兩條語句不能通過編譯,為什么呢,因為FileInputFormat.setInputPaths和 FileOutputFormat.setOutputPath的第一個參數都是Job,而不是JobConf,找了很多資料,由於對hadoop了解 少,所以找資料沒有方向感,這也是學習新東西效率低下的原因,如果有哪位大牛,知道怎么克服效率低下的問題,請不吝賜教!
后來,無意中,看到mapred包中也有這兩個類的定義,於是火箭速度修改為mapred下的包,OK,順利通過編譯!
下面還有 job.setOutputFormat(TextOutputFormat.class);語句編譯不同通過,提示參數需要擴展。。。 的參數;於是小菜也去mapred下面查找是否存在此類,正如期望,也存在此類,當即立段,修改為此包下的類,順利編譯通過,此時,頗有成就感!
可是現在小菜發現,mapred包下和mapreduce包下同時都存在又相應的類,不知道是為什么,那么下面就有目標的請教搜索引擎啦,呵呵,比剛才有很大進步。
結果令小菜很失望,就找到了一個符合理想的帖子。但是通過這個帖子,小菜知道了,mapred代表的是hadoop舊API,而mapreduce代表的是hadoop新的API。
OK,小菜在google輸入框中輸入“hadoop新舊API的區別”,結果很多。看了之后,又結合權威指南歸結如下:
1. 首先第一條,也是小菜今天碰到這些問題的原因,新舊API不兼容。所以,以前用舊API寫的hadoop程序,如果舊API不可用之后需要重寫,也就是上面我的程序需要重寫,如果舊API不能用的話,如果真不能用,這個有點兒小遺憾!
2. 新的API傾向於使用抽象類,而不是接口,使用抽象類更容易擴展。例如,我們可以向一個抽象類中添加一個方法(用默認的實現)而不用修改類之前的實現方法。因此,在新的API中,Mapper和Reducer是抽象類。
3. 新的API廣泛使用context object(上下文對象),並允許用戶代碼與MapReduce系統進行通信。例如,在新的API中,MapContext基本上充當着JobConf的OutputCollector和Reporter的角色。
4. 新的API同時支持"推"和"拉"式的迭代。在這兩個新老API中,鍵/值記錄對被推mapper中,但除此之外,新的API允許把記錄從map()方法中拉出,這也適用於reducer。分批處理記錄是應用"拉"式的一個例子。
5. 新的API統一了配置。舊的API有一個特殊的JobConf對象用於作業配置,這是一個對於Hadoop通常的Configuration對象的擴展。 在新的API中,這種區別沒有了,所以作業配置通過Configuration來完成。作業控制的執行由Job類來負責,而不是JobClient,並且 JobConf和JobClient在新的API中已經盪然無存。這就是上面提到的,為什么只有在mapred中才有Jobconf的原因。
6. 輸出文件的命名也略有不同,map的輸出命名為part-m-nnnnn,而reduce的輸出命名為part-r-nnnnn,這里nnnnn指的是從0開始的部分編號。
這樣了解了二者的區別就可以通過程序的引用包來判別新舊API編寫的程序了。小菜建議最好用新的API編寫hadoop程序,以防舊的API被拋棄!!!