import org.apache.spark.{SparkContext, SparkConf}
//这样引入是为引入reduceByKey
import org.apache.spark.SparkContext._
/**
在给定的莎士比亚文集上(多个文件),根据规定的停词表,统计出现频度最高的 100 个单词。
实现后的程序应该满足下列要求:输入指定文件夹下的所有莎翁文集文件,
停词表中出现的单词不计算词频,输出结果为出现频次最高的100个单词。
* Created by sucre on 2016/3/6.
*/
object WordCount1 {
def main(args: Array[String]) {
val appName = "WordCount"
//如果是在spark-shell执行,那么conf和sc是不用创建的;但是如何要用spark-submit执行scala
//的jar,那么conf和sc是需要的
val conf = new SparkConf().setMaster("local").setAppName(appName)
val sc = new SparkContext(conf)
val inputFiles = "/home/sucre/wordcount/shakespear/*"
val stopWordFile = "/home/sucre/wordcount/stopword.txt"
val inputRDD = sc.textFile(inputFiles)
val stopRDD = sc.textFile(stopWordFile)
/**
* 输入的文件内容里除了英文单词之外,还有下面的特殊符号,这些符号不应该计算到统计中:
制表符,反斜线,句号,逗号,竖线,中括号,问号,破折号,叹号,分号,其他英文符号
我们需要使用空格替换这些标点符号,同时将替换后的行拆分成单词。
*/
val targetList:Array[String] = Array[String]("""\t\().,?[]!;|""")
def replaceAndSplit(s:String):Array[String]={
for(c<-targetList){
s.replace(c," ")
}
s.split("\\s+")
}
val inputRDDv1 = inputRDD.flatMap(replaceAndSplit)
//将停词表里的空行去除并获得列表
val stopList = stopRDD.map(x=>x.trim()).collect()
//输入文件RDD中如果出现停词表中的单词,则去除该单词
val inputRDDv2 = inputRDDv1.filter(x=>stopList contains x)
//将每个单词Map到一个元组:(word,1)
val inputRDDv3 = inputRDDv2.map(x=>(x,1))
//通过reduce操作,根据上一步骤输出的元组中的单词以x为key,
// 将后面第二个元素的数字进行相加
val inputRDDv4 = inputRDDv3.reduceByKey(_ + _)
inputRDDv4.saveAsTextFile("/tmp/v4output")
//将词频统计的结果进行一次元组位置的交换,将频次放到第一个元素,而单词放到第二个元素
val inputRDDv5 = inputRDDv4.map(x=>x.swap)
//交换后进行按频次排序,参数ascending=False表示降序排列
val inputRDDv6 = inputRDDv5.sortByKey(false)
//排序后我们需要提取所有的单词,去掉元组中的频次信息,只需要单词列表
val inputRDDv7 = inputRDDv6.map(x=>x.swap).keys
//提取前100的元素
val top100 = inputRDDv7.take(100)
val outputFile="/tmp/result"
val result =sc.parallelize(top100)
result.saveAsTextFile(outputFile)
}
}
将以上代码编译成jar文件,然后用spark-submit去提交看看,代码中的inputFiles和outFiles可以写成两个参数,这样就可以做为通用的了。