Spark 大資料中文分詞統計(三) Scala語言實現分詞統計__spark

來源:互聯網
上載者:User

        Java版的Spark大資料中文分詞統計程式完成之後,又經過一周的努力,把Scala版的Spark

大資料中文分詞統計程式也搞出來了,在此分享給各位想學習Spark的朋友。

        如下是程式最終啟動並執行介面截圖,和Java版差別不大:

       

        如下是Scala工程結構:

          當你在工程主類檔案WordCounter.scala上單擊右鍵,選擇Run As Scala Application:

       然後選擇唐詩宋詞進行分詞統計,就會出現前面顯示的分詞結果。

       工程代碼已經上傳CSDN:http://download.csdn.net/detail/yangdanbo1975/9608632。

       整個工程結構很簡單,Text包中和Java工程中一樣,包含了內建的文字檔。整個工程引用的類庫和Java工程類似,只是多了Scala的內容。

需要注意的是,由於Scala版本的不同, Scala預設引用的類庫也有所不同,例如當選擇Eclipse內建的Scala 2.10.6版本時,swing類庫是自動引

入的,如下圖所示:

        可是,如果你選擇不同的Scala版本,比如最新下載安裝的2.1.18版,swing類庫就得自己手動載入了:

         你可以在工程屬性的Java Build Path -> Scala Library Container 中Edit Library,來切換Scala Library的版本:

       整個工程總共包括GuiUtils.scala,SparkWordCount.scala,TextPane.scala和WordCounter.scala四個Scala類和JavaUtil.java一個Java類。

       GuiUtils.scala完全複製自網上代碼,實現了類似 於Java Swing中OptionPanel的message 提示框的功能。

       TextPane.scala則複製自GitHub上的ScalaSwing2項目,把JTextPanel移植到了Scala中。標準的Scala Library直到2.1.18版本都沒有實現

TextPanel,只有TextArea,我們的工程中顯示分詞結果沿用了Java版的JTextPane,所以我們複製了這個Scala版的。

        SparkWordCount.scala類實現了Spark中文分詞統計的核心功能,是在DT 大資料夢工廠王家林老師的SparkWordCount的代碼基礎上改寫的。

        首先,把主要功能步驟從伴生對象的main方法中移到了SparkWordCount類中,並拆分為多個方法,使得伴生對象的main方法和後面的GUI介面

都能調用:

        class SparkWordCount {
               var sc:SparkContext = null;
 
               def initSpark(appName:String){
                     /**
                      * 第1步:建立Spark的設定物件SparkConf,設定Spark程式的運行時的配置資訊,
                      * 例如說通過setMaster來設定程式要連結的Spark叢集的Master的URL,如果設定
                      * 為local,則代表Spark程式在本地運行,特別適合於機器配置條件非常差(例如
                      * 只有1G的記憶體)的初學者       * 
                      */
                      val conf = new SparkConf() //建立SparkConf對象
                      conf.setAppName(appName) //設定應用程式的名稱,在程式啟動並執行監控介面可以看到名稱
                      conf.setMaster("local") //此時,程式在本地運行,不需要安裝Spark叢集
     
                     /**
                      * 第2步:建立SparkContext對象
                      * SparkContext是Spark程式所有功能的唯一入口,無論是採用Scala、Java、Python、R等都必須有一個SparkContext
                      * SparkContext核心作用:初始化Spark應用程式運行所需要的核心組件,包括DAGScheduler、TaskScheduler、SchedulerBackend
                      * 同時還會負責Spark程式往Master註冊程式等
                      * SparkContext是整個Spark應用程式中最為至關重要的一個對象
                      */
                      sc = new SparkContext(conf) //建立SparkContext對象,通過傳入SparkConf執行個體來定製Spark啟動並執行具體參數和配置資訊
                }
 
                def wordCount(doc:String, wordLength:Int):RDD[(String,Int)]={
                      /**
                       * 第3步:根據具體的資料來源(HDFS、HBase、Local FS、DB、S3等)通過SparkContext來建立RDD
                       * RDD的建立基本有三種方式:根據外部的資料來源(例如HDFS)、根據Scala集合、由其它的RDD操作
                       * 資料會被RDD劃分成為一系列的Partitions,分配到每個Partition的資料屬於一個Task的處理範疇
                       */
                        //val lines = sc.textFile("E://text//唐詩三百首.txt", 1) //讀取本地檔案並設定為一個Partion
                        //val lines = sc.textFile("src/com/magicstudio/spark/text/唐詩三百首.txt", 1)
                        val lines = sc.textFile(doc, 1) 
     
                        /**
                         * 第4步:對初始的RDD進行Transformation層級的處理,例如map、filter等高階函數等的編程,來進行具體的資料計算
                         *  第4.1步:講每一行的字串拆分成單個的單詞
                         */
     
                         //val words = lines.flatMap { line => line.split(" ")} //對每一行的字串進行單詞拆分並把所有行的拆分結果通過flat合并成為一個大的單詞集合
                         val words = lines.flatMap { line => JavaUtil.getSplitWords(line, wordLength).asScala }
                         /**
                          * 第4步:對初始的RDD進行Transformation層級的處理,例如map、filter等高階函數等的編程,來進行具體的資料計算
                          *  第4.2步:在單詞拆分的基礎上對每個單詞執行個體計數為1,也就是word => (word, 1)
                          */
                         val pairs = words.map { word => (word, 1) }
     
                         /**
                          * 第4步:對初始的RDD進行Transformation層級的處理,例如map、filter等高階函數等的編程,來進行具體的資料計算
                          *  第4.3步:在每個單詞執行個體計數為1基礎之上統計每個單詞在檔案中出現的總次數
                          */
                         val wordCounts = pairs.reduceByKey(_+_) //對相同的Key,進行Value的累計(包括Local和Reducer層級同時Reduce)
     
                          //added by Dumbbell Yang at 2016-07-24
                         wordCounts.sortBy(x => x._2 , false, wordCounts.partitions.size)
               }
 
               def outputResult(wordCounts:RDD[(String,Int)]){
                        wordCounts.foreach(wordNumberPair => println(wordNumberPair._1 + " : " + wordNumberPair._2))
               }
 
               def closeSpark(){
                       sc.stop()
                }

   }

        其次,在wordCount方法中,把原來第3步讀取固定檔案的方式改為參數方式,可以是src目錄下的相對檔案路徑(在GUI介面上通過下拉

框選擇),也可以是本地磁碟上的絕對檔案路徑(通過檔案瀏覽框選擇):

      //val lines = sc.textFile("E://text//唐詩三百首.txt", 1) //讀取本地檔案並設定為一個Partion
      //val lines = sc.textFile("src/com/magicstudio/spark/text/唐詩三百首.txt", 1)
      val lines = sc.textFile(doc, 1)

      然後就是第4.1步中,通過調用JavaUtil類中的java方法,實現了中文分詞功能,替換掉原來簡單的split,對每一行文本進行中文分詞:

      //val words = lines.flatMap { line => line.split(" ")} //對每一行的字串進行單詞拆分並把所有行的拆分結果通過flat合并成為一個大的單詞集合
      val words = lines.flatMap { line => JavaUtil.getSplitWords(line, wordLength).asScala }

      需要注意的是,由於需要調用Java功能,在Scala和Java之間進行資料傳遞,所以必須引用資料類型轉換的library:

      import collection.JavaConverters._

      然後,才可以對JavaUtil中的getSplitWords方法返回的結果進行asScala的轉換,使之能夠滿足Scala方法調用的要求。

      最後的一個改動,就是加上了一個對分詞統計結果按照詞頻進行排序的功能:

      //added by Dumbbell Yang at 2016-07-24
      wordCounts.sortBy(x => x._2 , false, wordCounts.partitions.size)

      可以對比Java方法實現排序時,交換key和value,排序,然後在交換回去的繁瑣,scala語言確實方便很多。

      經過以上改動之後,Spark中文分詞統計功能,既可以從main方法中調用,如伴生對象中原來的調用:

      /**
       * 使用Scala開發本地測試的Spark WordCount程式
       * @author DT大資料夢工廠
       * 新浪微博:http://weibo.com/ilovepains/
       */
object SparkWordCount{
 
    def main(args: Array[String]){
       val counter = new SparkWordCount
      
       counter.initSpark("Spark中文分詞統計")
      
       val words = counter.wordCount("src/com/magicstudio/spark/text/唐詩三百首.txt", 2)
      
       counter.outputResult(words)
      
       counter.closeSpark()
    }
}

      也可以從WordCounter.scala這個GUI介面程式中調用。

      WordCounter.scala類主要實現了Spark中文分詞統計程式的GUI介面,代碼也並不複雜,需要注意的有以下幾點:

      首先伴生對象聲明,最新的Scala Library中,是基於SimpleSwingApplication的:

      object WordCounter extends SimpleSwingApplication {

      但是在早期Scala Library中,這個類名字是SimpleGUIApplication,所以網上很多沒有及時更新的代碼,在新的Scala

Library下都需要修改類名才能編譯運行。

      其次,是關於Scala函數傳回值,文檔上只是說函數最後一個語句的傳回值就是函數的傳回值,但其實並不具體,經過

程式測試,其實應該說是最後一個執行語句的傳回值更確切些,而且應該指出在不同的條件下,會執行不同的邏輯,因而

最後一個執行語句並不是像很多例子中那樣,一定就是語句的最後一行,例如:

      def getDocPath():String={
           if (docField.text.isEmpty()){
                "src/com/magicstudio/spark/text/" + cboDoc.selection.item + ".txt"
           }
           else{
                docField.text
           }
      }

      再例如:

      def getTopN():Int={
           if (top50.selected){
               50
          }
          else if (top100.selected){
               100
          }
          else if (top500.selected){
               500
          }
          else if (top1000.selected){
               1000
          }
          else if (topAll.selected){
               0
          }
          else{
               0
          }
       }

       而且,傳回值不用寫return,直接運算式即可,充分體現了Scala語言孜孜以求的精簡。

       最後值得一提的是Scala和Java的相互調用功能,對於複用已有的Java開發的大量應用功能,意義深遠。

       在Scala工程中,你可以添加Java類,引用已有的Java類,用java方法實現很多功能,然後在Scala類中來調用,

例如,在本工程中,中文分詞功能就是通過java方法,引用IKAnalyzer組件在JavaUtil方法中實現的,在Scala類中

調用。再例如,JavaUtil中的其他方法,如:

public static void showRDDWordCount(JavaRDD<Tuple2<String, Int>> wordCount,
   int countLimit, String curDoc, JTextPane resultPane, JCheckBox chkClear)

        也是改寫自原來的Java工程中的源碼,在Scala類中引用,完成在GUI介面顯示分詞結果的功能。

        當然,為了在Scala中引用,對參數做了一些改動,如原來沒有傳遞介面控制項,現在改成傳遞Scala介面組件的

peer(對應的Java Swing組件),原來的分詞元組是Tuple2<String,Integer>,現在改成Tuple2<String,Int>,用Scala的

Int類型替換掉Java的Integer類型,因為Scala的RDD.toJavaRDD()方法產生的RDD是<String,Int>。而Java完全可以引

用Scala的Int類型(本來的Tuple2就是Scala的類型)。總而言之,Scala和Java相互調用的功能還是很強大,很方便的。

        以上便是對Scala語言實現Spark中文分詞統計的一個小小總結。以後有時間的話,我會繼續嘗試SparkStreaming,

Spark SQL等Spark其它相關技術,爭取全面掌握Spark。



   

     


     

     


聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.