1. 程式人生 > >hadoop入門(六)JavaAPI+Mapreduce例項wordCount單詞計數詳解

hadoop入門(六)JavaAPI+Mapreduce例項wordCount單詞計數詳解

剛剛研究了一下haoop官網單詞計數的例子,把詳細步驟解析貼在下面:

準備工作:

1、haoop叢集環境搭建完成

2、新建一個檔案hello,並寫入2行單詞,如下:

[[email protected] hadoop-2.6.0]# vi hello
hello   you
hello   me

3、把檔案傳到hdfs根目錄下:

[[email protected] hadoop-2.6.0]# bin/hdfs dfs -put hello /

檢視檔案是否匯入成功

[[email protected] hadoop-2.6.0]# bin/hdfs dfs -text /hello

hello   you
hello   me

4、開啟eclipse,如果你之前練過JavaAPI操作hdfs,那麼在原來專案中直接新增MapReduce的jar包就行了,Maven專案直接新增依賴就好。

 jar包在之前搭建Windows的hadoop環境下的C:\Program Files (x86)\hadoop-2.6.3\share\hadoop\mapreduce下的所有jar和此資料夾下lib中的所有jar.

如果之前沒做過hdfs練習,那麼其他jar請參考我的前幾篇文章Hadoop入門(三)。

準備工作做好了,下面就開始編碼,程式碼中我註釋的很詳細:

◆執行步驟:  1. map
任務處理 1.1 讀取輸入檔案內容,解析成key、value對。對輸入檔案的每一行,解析成key、value對。每一個鍵值對呼叫一次map函式。 1.2 寫自己的邏輯,對輸入的key、value處理,轉換成新的key、value輸出。 1.3 對輸出的key、value進行分割槽。 1.4 對不同分割槽的資料,按照key進行排序、分組。相同key的value放到一個集合中。 1.5 (可選)分組後的資料進行歸約。 2.reduce任務處理 2.1 對多個map任務的輸出,按照不同的分割槽,通過網路copy到不同的reduce節點。 2.2 對多個map任務的輸出進行合併、排序。寫reduce函式自己的邏輯,對輸入的key、values處理,轉換成新的key、value輸出。 2.3 把reduce的輸出儲存到檔案中。
package test;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.input.TextInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat;

public class WordCountApp {	
	
	/**我定義一個內部類MyMapper繼承Mapper類
	 * 泛型解釋:LongWritable是大資料裡的型別對應java中的Long型別
	 *         Text對應java裡的String型別,所以Mapper泛型前2個就是LongWritable, Text
	 * 邏輯解釋:由於我們做的是單詞計數,檔案中的單詞是下面2行
	 *         hello  you
	 *         hello  me
	 * 所以 ,根據上面
	 * 步驟1.1,則   <k1,v1>是<0, hello	you>,<10,hello	me> 形式   
	 * 檔案的讀取原則:<每行起始位元組數,行內容>,所以第一行起始位元組是0,內容是hello you
	 *             第二行起始位元組是10,內容是hello me,從而得出k1,v1
	 * 步驟1.2:如果我們要實現計數,我們可以把上面的形式通過下面的map函式轉換成這樣
	 * <k2,v2>--->  <hello,1><you,1><hello,1><me,1>
	 * 於是Mapper泛型後2個就是Text,LongWritable
	 *可以理解泛型前2個為輸入的map型別,後2個為輸出的map型別
	 */
	public static class MyMapper extends Mapper<LongWritable, Text, Text, LongWritable>{		
		//定義一個k2,v2
		Text k2 = new Text(); 
		LongWritable v2 = new LongWritable();
		@Override
		//下面的key就是從檔案中讀取的k1,value就是v1,map函式就是在執行步驟1.2
		protected void map(LongWritable key, Text value,
				Mapper<LongWritable, Text, Text, LongWritable>.Context context)
				throws IOException, InterruptedException {
			String[] words = value.toString().split("\t");
			for (String word : words) {
				//word表示每一行中的每個單詞,即k2
				k2.set(word);
				v2.set(1L);	//沒排序分組前每個單詞都是1個,由於是Long型別所以加L			
				context.write(k2, v2);//寫出
			}
		}
	}
	//步驟1.3:對輸出的所有的k2、v2進行分割槽去執行MapperTask
	//步驟1.4:shuffle-排序後的結果是<hello,1><hello,1><me,1><you,1>
	//        分組後的結果是<hello,{1,1}><me,{1}><you,{1}>
    //1.3和1.4,1.5是hadoop自動幫我們做的,我們做的就是上面寫的map函式的輸出邏輯
	
	/**
	 * 下面這個MyReducer函式是輸出<k3,v3>的函式,邏輯要我們自己寫。
	 * 傳入的引數是上面得到的<hello,{1,1}><me,{1}><you,{1}>
	 * 把這些map分給不同的ReducerTask去完成最後
	 * 輸出為<k3,v3>是<hello, 2>,<me, 1>,<you, 1>
	 */
	public static class MyReducer extends Reducer<Text, LongWritable, Text, LongWritable>{
		LongWritable v3 = new LongWritable();
		@Override
		//傳入的資料形如<hello,{1,1}>,V的值是個集合,所以這裡Iterable<LongWritable>
		protected void reduce(Text k2, Iterable<LongWritable> v2s,
				Reducer<Text, LongWritable, Text, LongWritable>.Context context)
				throws IOException, InterruptedException {
			long count = 0L;
			for (LongWritable v2 : v2s) {
				count += v2.get();
			}
			v3.set(count);
			//k2就是k3,都是一個單詞
			context.write(k2, v3);
		}
	}
	public static void deleteOutDir(Configuration conf, String OUT_DIR)
			throws IOException, URISyntaxException {
		FileSystem fileSystem = FileSystem.get(new URI(OUT_DIR), conf);
		if(fileSystem.exists(new Path(OUT_DIR))){
			fileSystem.delete(new Path(OUT_DIR), true);
		}
	}
	/**
	 * 上面我們把map,reduce都寫完了,下面我們把它們合在一起,運轉起來
	 */
	public static void main(String[] args) throws Exception {
		//載入驅動
		Configuration conf = new Configuration();
		//獲取job,告訴他需要載入那個類
		Job job = Job.getInstance(conf, WordCountApp.class.getSimpleName());
		//如果檔案達成jar包在hadoop執行必須做這個設定
		job.setJarByClass(WordCountApp.class);
		//獲取檔案資料
		FileInputFormat.setInputPaths(job, new Path("hdfs://192.168.19.128:9000/hello"));
		//通過TextInputFormat把讀到的資料處理成<k1,v1>形式
		job.setInputFormatClass(TextInputFormat.class);
		//job中加入Mapper,同時MyMapper類接受<k1,v1>作為引數傳給類中map函式進行資料處理
		job.setMapperClass(MyMapper.class);
		//設定輸出的<k2,v2>的資料型別
		job.setMapOutputKeyClass(Text.class);
		job.setMapOutputValueClass(LongWritable.class);
		//job中加入Reducer,Reducer自動接收處理好的map資料
		job.setReducerClass(MyReducer.class);
		//設定輸出的<k3,v3>的資料型別
		job.setOutputKeyClass(Text.class);
		job.setOutputValueClass(LongWritable.class);
		//設定輸出目錄檔案out1
		String OUT_DIR = "hdfs://192.168.19.128:9000/out1";
		FileOutputFormat.setOutputPath(job, new Path(OUT_DIR));
		job.setOutputFormatClass(TextOutputFormat.class);
		//如果這個檔案存在則刪除,如果檔案存在不刪除會報錯。
		deleteOutDir(conf, OUT_DIR);
		//把處理好的<k3,v3>的資料寫入檔案
		job.waitForCompletion(true);
	}
}
編碼完事了,建議不要再eclipse環境下執行,經常會出現很多錯誤。我們打成jar在linux的hadoop環境下執行

1、打jar包

在WordCountApp檔案上右鍵——》Export——》JAR file ——》next ——》在下面選個存放路徑並命名——》next——》next——》Main class選擇main函式所在的類也就是WprdCountApp這個類——》finish

2、把生成的wordCount.jar匯入到虛擬機器,我直接匯入到hadoop的安裝目錄下了 /usr/local/hadoop/hadoop-2.6.0/

3、在hadoop環境下執行這個jar

[[email protected] hadoop-2.6.0]# bin/hadoop jar wordCount.jar

................

.................

17/08/13 10:39:41 INFO mapred.LocalJobRunner: Finishing task: attempt_local730042948_0001_r_000000_0
17/08/13 10:39:41 INFO mapred.LocalJobRunner: reduce task executor complete.
17/08/13 10:39:41 INFO mapreduce.Job:  map 100% reduce 100%
17/08/13 10:39:41 INFO mapreduce.Job: Job job_local730042948_0001 completed successfully
17/08/13 10:39:42 INFO mapreduce.Job: Counters: 38

....................

..........................

看到上面的結果說明程式執行完畢map 100% reduce 100%

4、我們來看一下是否生成out1檔案,再看看檔案內容

[[email protected] hadoop-2.6.0]# bin/hdfs dfs -ls /

-rw-r--r--   3 root supergroup         19 2017-08-13 08:37 /hello
drwxr-xr-x   - root supergroup          0 2017-08-13 10:39 /out1

看看out1裡面有啥:

[[email protected] hadoop-2.6.0]# bin/hdfs dfs -ls /out1

-rw-r--r--   3 root supergroup          0 2017-08-13 10:39 /out1/_SUCCESS
-rw-r--r--   3 root supergroup         19 2017-08-13 10:39 /out1/part-r-00000

我們開啟part-r-0000看看裡面:

[[email protected] hadoop-2.6.0]# bin/hdfs dfs -text /out1/part-r-00000
hello   2
me      1
you     1

好了,單詞計數完成,hello2 個,me 1個,you 1 個。

相關推薦

hadoop入門JavaAPI+Mapreduce例項wordCount單詞計數

剛剛研究了一下haoop官網單詞計數的例子,把詳細步驟解析貼在下面: 準備工作: 1、haoop叢集環境搭建完成 2、新建一個檔案hello,並寫入2行單詞,如下: [[email protected] hadoop-2.6.0]# vi hello hello

Hibernate學習———— cascade(級聯)和inverse關係

序言         寫這篇文章之前,自己也查了很多的資料來搞清楚這兩者的關係和各自所做的事情,但是百度一搜,大多數博文感覺說的雲裡霧裡,可能博主自己清楚是怎麼一回事,但是給一個不懂的人或者一知半解的人看的話,別人也看不懂其中的關係,所以我自己寫博文的時候,會盡量用通俗通俗在通俗的語言去描述一個概念,希望能

【深度分析Zigbee】Zstack協議棧初窺:協調器的組網過程

這一講我要詳細說一下協調器的組網過程。在Zstack中,網路組網是從ZDApp_Init函式開始的。具體的執行流程為:Main()->osal_init_system()->osalInitTasks()->ZDApp_In it()。進入到ZDApp_I

微信小程式開發教程配置——app.json、page.json

全域性配置:app.json  微信小程式的全域性配置儲存在app.json檔案中。開發者通過使用app.json來配置頁面檔案(pages)的路徑、視窗(window)表現、設定網路超時時間值(networkTimeout)以及配置多個切換頁(tarBar)等。  首先看一

Maven快速入門Maven中的pom.xml檔案

上一章,我們講了Maven的座標和倉庫的概念,介紹了Maven是怎麼通過座標找到依賴的jar包的。同時也介紹了Maven的中央倉庫、本地倉庫、私服等概念及其作用。這些東西都是Maven最基本、最核心的概念,大家一定要搞明白。所謂工欲善其事必先利其器,這些基礎的東西一定要掌握。其實,Maven專案中還有一個最核

hadoop學習WordCount示例深度學習MapReduce過程1

        花了整整一個下午(6個多小時),整理總結,也算是對這方面有一個深度的瞭解。日後可以回頭多看看。         我們都安裝完Hadoop之後,按照一些案例先要跑一個WourdCount程式,來測試Hadoop安裝是否成功。在終端中用命令建立一個資料夾,簡單的

【轉】SVM入門線性分類器的求解——問題的轉化,直觀角度

content cli 樣本 image ges 五個 是你 角度 spa SVM入門(六)線性分類器的求解——問題的轉化,直觀角度 讓我再一次比較完整的重復一下我們要解決的問題:我們有屬於兩個類別的樣本點(並不限定這些點在二維空間中)若幹,如圖, 圓形的樣本點定為正樣

[轉]spring入門【springMVC中各數據源配置】

數據源 開源 文件 mysql 簡單 oot img log 自帶 在使用spring進行javaWeb開發的過程中,需要和數據庫進行數據交換,為此要經常獲取數據庫連接,使用JDBC的方式獲取數據庫連接,使用完畢之後再釋放連接,這種過程對系統資源的消耗無疑是很大的,這裏簡單

轉:TensorFlow入門 雙端 LSTM 實現序列標註分詞

vsm max poc 代碼 單詞 arch 大致 雙端 fun http://blog.csdn.net/Jerr__y/article/details/70471066 歡迎轉載,但請務必註明原文出處及作者信息。 @author: huangyongye @creat_

verilog入門-----用戶定義原語UDP

reg verilog log ndt syn sync 出現 表示 tab 用戶定義原語UDP 1.UDP的定義 UDP說明定義如下: primitive UDP_name (OutputName,List_of_inputs) Output_declara

Spring Boot快速入門:thymeleaf

return 之前 err static 默認 示例 圖片資源 css 官網 原文地址:https://lierabbit.cn/articles/8 靜態資源 在我們開發Web應用的時候,需要引用大量的js、css、圖片等靜態資源。 Spring Boot的默認位置是re

08-Linux基礎入門-文件和目錄的屬性及權限之文件類型、文件擴展名及文件權限基礎

ins tmp first 串口 .py 都是 公眾平臺 cond .com 一、Linux中的文件類型在Linux系統中,可以說一切(包括目錄、普通文件、設備文件等)皆為文件。文件類型包含有普通文件、目錄、字符設備文件、設備文件、符號鏈接文件、管道文件等等,當執行ls

Java入門:數組

屬性 array 初始 圖片 nbsp 遍歷 屬性。 語法 規則 數組是一種數據結構,用於存儲同一類型值的集合,也可以看做是數據類型一致的一組數據。 一、語法和聲明數組 1、語法:數據類型[ ] array = new 數據類型[長度]; 註意: 使用長度創建數組的時候,每

python入門裝飾器的理解

裝飾器裝飾器用於拓展原有函數功能的一種函數比如: def helloWorld(fun) def out() print ("======start========") fun() print ("

Netty入門Decoder解碼器

err 器) repl 方法 pub HA override 異常 oid   Netty 提供了豐富的解碼器抽象基類,主要分為兩類: 解碼字節到消息(ByteToMessageDecoder 和 ReplayingDecoder) 解碼消息到消息(MessageTo

學習筆記版Hadoop入門:Hadoop2.7.3完全分布式集群安裝

min property per cal mon 分別是 master 修改 node 在這裏寫下安裝hadoop2.7.3版本的完全分布式的過程,因為剛開始學習hadoop不久,希望自己把學習的東西記錄下來,和大家一起分享,可能有錯誤的地方,還請大牛們批評指正,在我學習的

區塊鏈快速入門——區塊鏈密碼學與安全相關技術

ocs 國家 發出 .com 少包 signature payment 有效期 保護 區塊鏈快速入門(六)——區塊鏈密碼學與安全相關技術 一、區塊鏈密碼安全技術簡介 區塊鏈和分布式賬本中大量使用了密碼學和安全技術的最新成果,特別是身份認證和隱私保護相關技術。區塊鏈使用了包括

06 React快速入門——使用css樣式

      在react中元件使用樣式主要有兩種方式:內聯式和外聯式。下面分別介紹兩種方式:       一、內聯式       使用內聯樣式,和html中差不多,不多在此處需要注意的是,通過sty

Java的繼承與記憶體結構——有C++基礎的Java入門

目錄 一、 繼承概念 1、語法 2、 例項  3、 總結 二、 繼承的記憶體結構 一、 繼承概念 繼承是面向物件最顯著的一個特性。繼承是從已有的類中派生出新的類,新的類能吸收已有類的資料屬性和行為,並能擴充套件新的能力。 通俗一點:描述事物的時候,如

快速入門完整:Python例項100個基於最新Python3.7版本

Python3 100例 原題地址: http://www.runoob.com/python/python-100-examples.html git地址: https://github.com/RichardFu123/Python100Cases 轉載請標註: https: