此常規Java項目,不是Maven項目,也不是Java Enterprise項目。html
打開 File->New->Project菜單,選擇Java便可,逐步點擊Next,在目錄D:\Java\hadoop\mr下建立一個項目名稱。java
這裏咱們建立的項目叫groupbysum,表示groupbysum MapReduce小項目。apache
之後各類功能的mapreduce程序均已小項目形式放在mr目錄下。數組
其實咱們也能夠把mr建立爲一個項目(相似空間),各個小mapreduce程序做爲modules(項目)放在該項目(空間)下,但這種方式通常是是大項目,分組協同開發各個模塊功能的時候使用較多,這裏就不採用了,一次只開發一個項目。網絡
導入執行mapreduce程序依賴的Hadoop包:app
Apache Commons IO : 主要是文件處理,好比複製、輸入輸出、文件名處理、大小寫敏感等等。框架
The Apache Commons IO library contains utility classes, stream implementations, file filters, file comparators, endian transformation classes, and much more. 函數
導入操做:打開項目結構(CTRL+ALT_SHIFT+S 或者使用工具欄的 圖標 ),點擊Modules,切換tab標籤到Dependencies,點擊 + 加號,選擇準備好的包含這些Jar包的目錄D:\Java\hadoop\jar,到這裏功能上已經能夠用了,可是爲了便於區分管理咱們導入的Jar包,這裏能夠點擊這個目錄,選擇右側的小鉛筆(EDIT),給這些包在這個項目裏起一個分組名稱,這裏咱們起了hadoop-2.7.6。工具
寫Java類,一般有兩種方式,一種是類中類,只寫一個Java文件,一種是一個類一個Java文件,多個Java文件。oop
這裏咱們選擇分開寫,增長對mapreduce原理對認識和理解。
建立包體,右擊src,new->package,輸入包名,這裏咱們命名包爲com.leeyk99.com。(這個包名寫的瞎眼了,後續會寫com.leeyk99.hadoop)
重點參考:
https://www.cnblogs.com/bovenson/p/6275762.html?utm_source=itdadao&utm_medium=referral
我的學習的Java代碼(文件和目錄io代碼 ioReadWrite.java)
意外發現:
由於以前在公司經過Maven建立了WordCount官方示例MR項目,僅在pom.xml中配置了最重要的幾個Hadoop jar包依賴,成功運行。實際上Maven項目自動下載了相關的jar包,好比jackson-core-asl-1.9.13.jar、commons-configuration-1.10.ja等。
<!-- 基礎依賴hadoop-core和hadoop-common --> <!--hadoop-core的version通常爲1.2.1--> <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-core</artifactId> <version>1.2.1</version> </dependency> <!--hadoop-common的version能夠依照你的實際須要來--> <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-common</artifactId> <version>2.7.6</version> </dependency> <!--若是須要讀寫HDFS,則還須要依賴hadoop-hdfs和hadoop-client--> <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-hdfs</artifactId> <version>2.7.6</version> </dependency> <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-client</artifactId> <version>2.7.6</version> </dependency>
在這個普通Java項目導入第2步指定的jar包,報告了不少類缺失錯誤,最後都一一找來了。故,實際依賴完整的Jar包以下:
導入這些包後,運行無誤。
故,在對Hadoop的包的功能基本瞭解或者實際開發的時候,爲提升效率,可使用Maven項目。
本次Hadoop MR學習總結,主要集中在對總體運行邏輯和局部編寫細節的學習和測試,源碼原理未研究。
該MR程序測試了單度量在單維度上聚合統計的情形,即經常使用的:
select dim_a,sum(kpi_a) from table_name group by dim_a
GroupBySumMapper類繼承抽象類:org.apache.hadoop.mapreduce.Mapper (新API)。(舊API:extends MapReduceBase implements Mapper<LongWritable, Text, Text, DoubleWritable>)
Mapper是一個泛型類型,有四個形參,分別是map函數的輸入鍵、輸入值、輸出鍵、輸出值。泛型類型的形參只能是引用類型,不能是原始類型(如int、double、char)。
Hadoop提供了一套可優化網絡序列化傳輸的引用類型(LongWritable、Text、DoubleWritable、IntWritable),而不是直接用Java的引用類型(Long、String、Double、Integer,被hadoop提供的四個類型替代).
map函數是對一行記錄進行處理,數據集的每一行是輸入,輸入鍵就是相對於文件起始位置的偏移量(若是從第一行開始,就是行號了),由於Hadoop一般是處理大數據量,所以輸入鍵類型一般指定爲 LongWritable.
獲取到一行記錄後,將行轉換成成Java的String類型,提取相應的數據域(列),經常使用的方法:
獲取到指定數據域後,conntext.write將結果輸出,寫出到臨時文件,做爲reduce函數的輸入。
map任務將其輸出寫到本地硬盤,而非HDFS。由於map的輸出只是中間結果,一旦做業完成,map的輸出便可以刪除,存儲到HDFS並實現備份,不免小題大作(說白了,佔用存儲,數據備份也須要時間和帶寬)。
reduce函數以map的輸出做爲輸入,所以reduce函數的輸入鍵、輸入值和map的輸出鍵、輸出值類型須要是一致的,這種狀況下reduce函數的輸出類型也必須是Text和DoubleWritable。
reduce函數實現的操做一般是對輸入值的遍歷處理,好比求和、計數、比較、取均、去重等多種運算,而後將結果輸出,寫入到HDFS,做爲最終產出結果。
Job對象指定做業執行規範。能夠將代碼打包成Jar文件,發不到Hadoop集羣。沒必要指明JAR文件名稱,在Job對象的setJarByClass(GroupBySumRun.class)方法中傳遞類便可。Hadoop會根據這個類查找相關的JAR文件.
構造Job對象後,指定輸入(調用FileInputFormat類的靜態方法addInputPath(),能夠屢次調用實現多路徑輸入,路徑能夠是單個文件、一個目錄、符合特定模式的一些列文件)、輸出(調用FileOutputFormat類的靜態方法setOutputPath(),只能一個,且在運行前不能存在)路徑。
接着setMapperClass、setReducerClass指定要使用的map類型、reduce類型。至於setCombinerClass根據須要來使用。combiner是對map的輸出在MR框架混洗後的分組結果,進行組內計算,減小須要傳遞給reduce函數的數據量。
setOutputKeyClass()、setOutputValueClass()控制reduce函數的輸出類型,而且必須和Reduce類產生的相匹配,map函數的輸出類型默認狀況下和reduce函數是相同的,所以mapper產生出和reducer函數相同的類型時,不須要單獨設置map的輸出類型,不然須要經過setMapOutputKeyClass()、setMapOutputValueClass()方法來設置map函數的輸出類型。
文件的輸入輸出:
輸入的類型經過輸入格式來控制,setInputFormatClass(),若是不指定,則使用默認的格式TextInputFormat.class(文本輸入格式);
輸出的類型經過輸出格式來控制,setOutputFormatClass(),若是不指定,則使用默認的格式TextOutputFormat.class(文本輸入格式).
設置完成後,能夠開始運行做業。waitForCompletion()方法提交做業並等待執行完成。其參數true表示做業會把其進度信息寫到控制檯,返回結果是布爾值,true-成,false-敗。
這個例子的代碼不是最簡潔的,後續參照《Hadoo權威指南》再寫個 簡潔點的。
因爲reduce函數的輸出目錄在運行前必須不存在,爲方便調試代碼,不用每次都去手動刪目錄,寫了DelOutputDir類,在提交做業前執行刪除output目錄及其目錄下文件的方法。
這個方法要求output目錄裏只有文件,不能有目錄,由於代碼未對子目錄做處理。
使用Intellij IDEA建立一個常規Java項目,導入外部依賴。參見一、2步。
這裏未使用導入libraries的方法(這個是最推薦的方法,建立lib目錄,添加JAR文件,後續嘗試)。
Inerllij IDEA將程序打包成JAR文件,主要是作兩件事:1.建立MANIFEST.MF文件,這個文件指定MAIN CLASS的位置(包);2.將MANIFEST.MF和編譯後的class文件一塊兒打包。
打開IDEA的項目結構 (CTRL+SHILT+ALT+S 或者 快捷圖標 ),在Artifacts菜單中新建一個空JAR文件,若是有就進行配置便可。流程步驟:(未完待續)
6.代碼、JAR包、測試數據下載
https://files.cnblogs.com/files/leeyuki/code.rar 代碼
JAR包大於10M,博客園傳不了,如須要自行下載或留言索取。