1. 程式人生 > >Java筆記---Hadoop 2.7.1下WordCount程式詳解

Java筆記---Hadoop 2.7.1下WordCount程式詳解

一、前言

在之前我們已經在 CenOS6.5 下搭建好了 Hadoop2.x 的開發環境。既然環境已經搭建好了,那麼現在我們就應該來乾點正事嘛!比如來一個Hadoop世界的HelloWorld,也就是WordCount程式(一個簡單的單詞計數程式)

二、WordCount 官方案例的執行

2.1 程式簡介

WordCount程式是hadoop自帶的案例,我們可以在 hadoop 解壓目錄下找到包含這個程式的 jar 檔案(hadoop-mapreduce-examples-2.7.1.jar),該檔案所在路徑為 hadoop/share/hadoop/mapreduce。

我們可以使用 hadoop jar

命令檢視該jar包詳細資訊。執行命令:hadoop jar hadoop-mapreduce-examples-2.7.1.jar

wc1

可以看到,該 jar 檔案中並不止有一個案例,當然我們此時只想看看 WordCount 程式,其他的靠邊邊。那麼我們按照提示,執行命令:hadoop jar hadoop-mapreduce-examples-2.7.1.jar wordcount 看看有什麼東西?
wc2

根據提示,它說是需要輸入檔案和輸出目錄,那麼接下來,我們就準備以下輸入檔案和輸出目錄吧。

注:其實只需要準備輸入檔案,不需要準備輸出目錄。因為 MapReduce 程式的執行,其輸出目錄不能是已存在的,否則會丟擲異常。
這是為了避免資料覆蓋的問題。請看《Hadoop權威指南》

2.2 準備材料

為了方便使用該官方 jar 檔案,我們在當前目錄下建立一個 input 目錄(你也可以在別的目錄下建立目錄,目錄名也可以自己取,喜歡就好),用來存放輸入檔案。然後準備2個輸入檔案。如下所示:
wc3

因為我們是使用 HDFS 檔案系統的,所以我們要執行 WordCount 這個 MapReduce 程式的話,需要將檔案放入 HDFS 上。因此我們使用 HDFS 的檔案系統命令,在HDFS檔案系統根目錄下建立一個input目錄,用來儲存輸入檔案。執行命令:hadoop fs -mkdir /input
wc4

注:hadoop fs -mkdir 命令是用來在 HDFS 上建立目錄的,類似於Linux下的 mkdir 命令

目錄建立好後,我們需要把剛剛在本地檔案系統上準備的輸入檔案拷貝到 HDFS 上。執行命令:hadoop fs -put input/f*.txt /input
wc5

2.3 執行程式

準備工作就緒了,那麼現在就開始執行程式了。執行命令:hadoop jar hadoop-mapreduce-examples-2.7.1.jar wordcount /input /output

注:hadoop jar hadoop-mapreduce-examples-2.7.1.jar wordcount /input /output詳解
- 該命令中 /input 表示使用 HDFS 上根目錄(/)下的 input 目錄下所有檔案作為程式輸入
- /output 表示使用 HDFS 根目錄下的 output 目錄儲存程式的輸出(該 output 檔案,是本來不存在的,會由程式自動建立)

從終端可以看到如下命令輸出:
wc6
wc7
wc8

程式執行完畢,我們看一下輸出都有啥,執行命令:hadoop fs -cat /output/*
wc9

注:hadoop fs -cat 命令功能類似於linux下的 cat 命令

從上面的輸出,可以看到該程式將我們的輸入檔案中的單詞出現情況,進行了統計。都是 key,value 的形式出現的

三、WordCount 官方程式的原始碼分析

3.1 檢視原始碼

剛剛已經執行WordCount程式爽了一把,現在我們通過檢視原始碼來看看該程式的真面目。

我們使用 Eclipse 來檢視原始碼。在 hadoop-mapreduce-examples-2.7.1.jar 檔案所在目錄中,有一個 source 目錄,其中就存有該 jar 對應的 hadoop-mapreduce-examples-2.7.1-sources.jar。通過 Eclipse 檢視的情況如下:

sr1
sr2

可以看到該程式很簡單,程式碼量很少。其中內建了2個內部類,分別繼承字 Mapper 和 Reducer 類。這其實就是編寫 MapReduce 程式時,我們需要進行的工作。

3.2 分析程式結構

程式大概結構如下:(此處只簡單說一下,待會兒在自實現的 WordCount 中進行詳細的程式碼註釋)
① Mapper 區:繼承自 Mapper 類的一個內部類,實現 map() 函式
② Reducer 區:繼承自 Reducer 類的一個內部類,實現 reduce() 函式
③ Client 區:程式執行入口

這個結構,也就是 MapReduce 程式編寫的基本結構了。編寫一個 MapReduce 程式,我們程式猿只需要實現 map() 和 reduce() 程式。

3.3 自實現 WordCount

我們按照 MapReduce 程式的編寫情況,實現一個我們自己的 WordCount 程式。

① 建立一個 Java Project
② 匯入如下 jar 包
lib

注:其中 hadoop-hdfs-2.7.1.jar 和 hadoop-mapreduce-client-core-2.7.1.jar 是編寫程式需要的 jar 包,其他的 jar 包是我們在 linux 下執行程式需要的依賴 jar,也就是環境需要的 jar 包。

③ 編寫程式:WordCount.java

import java.io.IOException;
import java.util.StringTokenizer;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
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.output.FileOutputFormat;

/**
 * WordCount:MapReduce初級案例,按八股文的結構遍寫
 * @author johnnie
 *
 */
public class WordCount {

    /** 
     * Mapper區: WordCount程式 Map 類
     * Mapper<KEYIN, VALUEIN, KEYOUT, VALUEOUT>:
     *        |       |           |             |
     *  輸入key型別  輸入value型別      輸出key型別 輸出value型別
     * @author johnnie
     *
     */
    public static class TokenizerMapper extends Mapper<LongWritable, Text, Text, IntWritable>{
        // 輸出結果
        private Text word = new Text();                             // KEYOUT
        // 因為若每個單詞出現後,就置為 1,並將其作為一個<key,value>對,因此可以宣告為常量,值為 1
        private final static IntWritable one = new IntWritable(1);  // VALUEOUT

        /**
         * value 是文字每一行的值 
         * context 是上下文物件
         */
        @Override
        public void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
            // 獲取每行資料的值
            String lineValue = value.toString();
            // 分詞:將每行的單詞進行分割,按照"  \t\n\r\f"(空格、製表符、換行符、回車符、換頁)進行分割
            StringTokenizer tokenizer = new StringTokenizer(lineValue);
            // 遍歷
            while (tokenizer.hasMoreTokens()) {
                // 獲取每個值
                String wordValue = tokenizer.nextToken();
                // 設定 map 輸出的 key 值
                word.set(wordValue);
                // 上下文輸出 map 處理結果
                context.write(word, one);
            }
        }
    }

    /** 
     * Reducer 區域:WordCount 程式 Reduce 類
     * Reducer<KEYIN, VALUEIN, KEYOUT, VALUEOUT>:Map 的輸出型別,就是Reduce 的輸入型別
     * @author johnnie
     *
     */
    public static class IntSumReducer extends Reducer<Text, IntWritable, Text, IntWritable> {
        // 輸出結果:總次數
        private IntWritable result = new IntWritable();

        @Override
        public void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {
            int sum = 0;                        // 累加器,累加每個單詞出現的總次數
            // 遍歷values
            for (IntWritable val : values) {
                sum += val.get();               // 累加
            }
            // 設定輸出 value
            result.set(sum);
            // 上下文輸出 reduce 結果
            context.write(key, result);
        }
    }

    // Driver 區:客戶端
    public static void main(String[] args) throws Exception {
        // 獲取配置資訊
        Configuration conf = new Configuration();
        // 建立一個 Job
        Job job = Job.getInstance(conf, "word count");      // 設定 job name 為 word count
//      job = new Job(conf, "word count");                  // 過時的方式
        // 1. 設定 Job 執行的類
        job.setJarByClass(WordCount.class);

        // 2. 設定Mapper類和Reducer類
        job.setMapperClass(TokenizerMapper.class);
        job.setReducerClass(IntSumReducer.class);   

        // 3. 獲取輸入引數,設定輸入檔案目錄和輸出檔案目錄
        FileInputFormat.addInputPath(job, new Path(args[0]));
        FileOutputFormat.setOutputPath(job, new Path(args[1]));

        // 4. 設定輸出結果 key 和 value 的型別
        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(IntWritable.class);
//      job.setCombinerClass(IntSumReducer.class);

        // 5. 提交 job,等待執行結果,並在客戶端顯示執行資訊,最後結束程式
        boolean isSuccess = job.waitForCompletion(true);

        // 結束程式
        System.exit(isSuccess ? 0 : 1);
    }

}

④ 編寫 Main.java:我們配置一個程式執行入口,方便以後新增其他的示例,做成官方 jar 的樣子
main1
main2

⑤ 我們將該專案打包成可執行 jar包:此處我將該 jar 取名為 WordCount.jar
⑥ 利用 FileZilla 將該 jar 包上傳到 CenOS6.5 上
⑦ 利用 hadoop jar 命令來執行程式。執行命令:hadoop jar wordcount.jar WordCount ./data/f*.txt /out

注:這種傳參方式就是 Linux下引數傳遞的方式。這裡也介紹了我們平時在 Java 程式中 main() 中 args 的使用--就是來接受命令列引數的。

具體的步驟,還是和剛剛一樣,準備輸入檔案,以及指定輸出目錄。輸入檔案和輸出目錄的路徑都是在 HDFS 檔案系統上的。./data/f*.txt 也和剛剛的 f1.txt 和 f2.txt 差不多。輸出結果也不多說了,也差不多。

相關推薦

Java筆記---Hadoop 2.7.1WordCount程式

一、前言 在之前我們已經在 CenOS6.5 下搭建好了 Hadoop2.x 的開發環境。既然環境已經搭建好了,那麼現在我們就應該來乾點正事嘛!比如來一個Hadoop世界的HelloWorld,也就是WordCount程式(一個簡單的單詞計數程式) 二、

CentOS7用jdk1.8編譯hadoop-2.7.1全過程

說實話,本人編譯hadoop的過程比較曲折,但收穫也很多,下面系統介紹一下CentOS7下編譯hadoop-2.7.1的全過程吧。 1.工具準備,最靠譜的是hadoop說明文件裡要求具備的那些工具。 解壓之 tar -zxvf hadoop-

Linux鞏固記錄(5) hadoop 2.7.4自己編譯代碼並運行MapReduce程序

parser mod pill self add let tokenize org cto 程序代碼為 ~\hadoop-2.7.4\share\hadoop\mapreduce\sources\hadoop-mapreduce-examples-2.7.4-sourc

Hadoop-2.7.1叢集環境搭建

摘自:http://blog.csdn.net/u014039577/article/details/49813531 由於日誌資料量越來越大,資料處理的邏輯越來越複雜,同時還涉及到大量日誌需要批處理,當前的flume-kafka-storm-Hbase-web這一套流程已經不能滿足當前的需求了,所以只

hadoop-2.7.3的WordCount測試

測試hadoop的 WordCount 1、建立兩個文字 [[email protected] /]# mkdir input [[email protected] /]# cd input [[email protected] input

Java 資料結構2:棧及Stack原始碼

棧 棧,相信大家都非常熟悉了,先進先出,後進後出,又叫做LIFO(先進先出)表,一般棧的模型是,存在某個元素位於棧頂,而該元素是唯一的可見元素 棧的實現方式 1、通過單鏈表,通過在表的頂端插入實現樸實,通過刪除表頂端元素實現pop,top操作知識考察表

大資料筆記--hadoop中的hdfs寫資料流程

上圖是一個簡版的流程圖,圖畫的不標準,但能說明問題就OK,下面是根據上圖描述的寫資料流程,如有不對的地方請指教。 注:以下簡化名稱所對應的全稱: NN == NameNode; IO == hdfsFileoutputStream; DN == DataNod

MapReduce之WordCount程式及常見錯誤彙總

前言:     在之前的筆記中,我們已經成功的關聯了eclipse和hadoop,對FileSystem的使用進行了簡單瞭解。     下面就是Hadoop中的重點MapReduce程式的開發。作為MapReduce(以下使用MR來代替)開發中的入門程式WordCount

大資料學習系列8-Centos6.7 hadoop-2.6.5sqoop-1.4.6的安裝部署

安裝sqoop的前提是已經具備java和hadoop的環境 1、下載並解壓 2、修改配置檔案 $ cd $SQOOP_HOME/conf $ mv sqoop-env-template.sh sqoop-env.sh 開啟sqoop-env.sh並編輯下面幾

Hadoop-2.7.3環境Hive-2.1.1安裝配置。

環境:ubuntu-16.0.4;jdk1.8.0_111;apache-hadoop-2.7.3;apache-hive-2.1.1。這裡只記錄Hive的安裝。Hive只需要安裝到一個節點上即可。我這裡是裝在Namenode上的。首先從官網上下載所需要的版本,本人下載的ap

【轉載】Hadoop 2.7.3 和Hbase 1.2.4安裝教程

啟動 運行 property new rop net 文本文 .tar.gz cor 轉載地址:http://blog.csdn.net/napoay/article/details/54136398 目錄(?)[+] 一、機器環境

Hadoop 2.7.4 + HBase 1.2.6 + ZooKeeper 3.4.10

配置文件 title 2.6 ase keep itl 配置 oop hadoop 1: Hadoop 環境準備 2: hadoop的配置文件設置(非HA) 3: ZooKeeper 安裝與配置Hadoop 2.7.4 + HBase 1.2.6 + ZooKeeper 3

CentOS 7 快速架設hadoop 2.5.1叢集

經過幾天的折騰,總算成功了~賬號註冊到現狀近N年了,這是第一篇部落格~ 1、軟體準備a.OS:CentOS-7.0-1406-x86_64-DVD.iso --去CentOS官網下 b.JDK:jdk-7u71-linux-x64.gz --oracle官網下,至於1

Hadoop權威指南-大資料的儲存與分析第四版——學習筆記——第2章——1

MapReduce 適合處理半結構化的資料 MapReduce任務階段 Map階段+Reduce階段 Key-Value作為輸入輸出 實現兩個函式:map(),reduce() Map階段 輸入的Key:文字中的偏移量 輸入的value:文字 輸出的k-v給reduce處

並行作業2:Ubuntu(16.04)安裝配置hadoop(2.7.3)

Ubuntu(16.04)下安裝配置hadoop(2.7.3) 系統採用vm下ubuntu16.04 一、Java環境搭建(參考我的其它部落格) 二、安裝ssh-server並實現免密碼登入 1、下載安裝ssh-server sudo apt-get install op

CentOS6.5安裝Hadoop-2.7.3(圖解教程)

17. node 內容 apr ddbd 忽略 passwd frame shuffle 註:圖片如果損壞,點擊文章鏈接:https://www.toutiao.com/i6627365258090512909/ 安裝好虛擬機(3個節點) YUM源已安裝好、系統版本Ce

VirtualBox+Centos7+(jdk1.7.0_71+Hadoop-2.6.0)/(jdk1.10+Hadoop-2.9.1)搭建完全分散式叢集平臺

VirtualBox+Centos7+(jdk1.7.0_71+Hadoop-2.6.0)/(jdk1.10+Hadoop-2.9.1)搭建完全分散式叢集平臺 本文有很多是自定義的,可以根據自己的實際情況和需求修改,儘量會用紅色標註出來,當然按照步驟,一步一步應該也能成功,不

CentOS 7 搭建 Hadoop 2.9.1 遇到的坑之 storage directory does not exist or is not accessible.

2018-06-14 11:42:28,500 WARN org.apache.hadoop.hdfs.server.common.Storage: Storage directory /home/hadoopCluster/hadoop-2.9.1/tmp/dfs/name

hadoop-2.7 在windows環境安裝

    最近折騰檔案系統,用到了Hadoop,雖然專案是部署在Linux下的。但自己平時開發用的是windows系統(本人用的是win10 64bit)。為了方便開發和除錯,所以打算在windows環境下安裝hadoop。         往上找了幾篇文章,都說得

在 CentOS 7.2 安裝 Hadoop 2.7.5 並搭建偽分散式環境的方法

資源下載 一、建立 Hadoop 使用者 建立 hadoop 使用者,並分配以使用者名稱為家目錄/home/hadoop,並將其加入到sudo使用者組,建立好使用者之後,以 hadoop 使用者登入: sudo useradd