题目
使用Spark实现单词计数(Word Count)
信息
- 类型:问答
- 难度:⭐
考点
RDD基础操作,转换算子(transformations),行动算子(actions),键值对处理
快速回答
使用Spark实现单词计数的核心步骤:
- 使用
flatMap将每行文本拆分成单词 - 使用
map将每个单词转换为(word, 1)键值对 - 使用
reduceByKey对相同单词的计数求和 - 使用
collect或take触发计算并获取结果
原理说明
单词计数是Spark的经典入门案例,主要考察RDD的转换算子和行动算子:
- 转换算子(Transformations):惰性操作(如flatMap, map, reduceByKey),只记录计算逻辑不立即执行
- 行动算子(Actions):触发实际计算(如collect)
- 键值对处理:reduceByKey在相同键上执行聚合操作
代码示例
import org.apache.spark.{SparkConf, SparkContext}
object WordCount {
def main(args: Array[String]): Unit = {
// 1. 创建SparkContext
val conf = new SparkConf().setAppName("WordCount").setMaster("local[*]")
val sc = new SparkContext(conf)
// 2. 读取文本文件创建RDD
val textRDD = sc.textFile("data.txt")
// 3. 转换操作
val resultRDD = textRDD
.flatMap(_.split(" ")) // 拆分单词
.map(word => (word, 1)) // 转换为键值对
.reduceByKey(_ + _) // 按单词聚合计数
// 4. 行动操作触发计算
resultRDD.collect().foreach(println)
sc.stop() // 关闭SparkContext
}
}最佳实践
- 资源管理:使用
sc.stop()释放资源 - 数据清洗:可在split前添加
.toLowerCase().trim()统一大小写 - 性能优化:避免使用
groupByKey(性能差),优先用reduceByKey - 结果检查:使用
take(10)替代collect()避免Driver内存溢出
常见错误
- 混淆map/flatMap:误用
map(_.split(" "))会生成嵌套数组 - 忘记行动算子:仅用转换算子不会触发计算
- 资源泄漏:未调用
sc.stop() - 单词分隔:简单空格拆分会忽略标点(需正则处理如
split("\\W+"))
扩展知识
- DataFrame实现:现代Spark推荐使用Dataset API:
spark.read.text("data.txt")
.select(explode(split($"value", " ")).as("word"))
.groupBy("word").count() - 宽窄依赖:
reduceByKey属于宽依赖(需shuffle) - 执行计划:通过
resultRDD.toDebugString查看RDD血缘关系