入门Spark的第一个小例子就是编写一个简单的WordCount程序,来统计一个文件中每个单词的个数。接下来分别是用Scala、Python和Java三种语言来实现WordCount的代码,都是基于Spark2.0+版本和本地local模式。
编写Spark应用程序选择哪种语言?
首先,推荐使用Scala,因为Spark的底层源码主要是基于Scala编写的,对Scala的支持最友好,而且Scala这种函数式编程语言编写代码比较简洁,建议首选Scala。
其次,推荐使用Python编写Spark应用程序,但是性能会稍差,而且Spark的新功能对Python的支持也稍差。如果要用编写机器学习程序,建议使用Python,因为Python提供了丰富的类库。
最后,才推荐使用Java,因为代码写起来是在太冗余了,不过Spark对Java的支持要比Python好的多。
当然你也可以用R语言,不过支持是最差的。
Scala版本
import org.apache.spark.sql.SparkSession
object ScalaWordCount {
def main(args: Array[String]): Unit = {
// SparkSession实例, 也就是Spark任务的入口
val spark = SparkSession
.builder()
.appName("ScalaWordCount")
.master("local[4]") // 本地模式, 使用4个cpu cores
.getOrCreate()
//读取本地的一个txt文件, 里面是随意copy进去的一些英文文章片段
val lines = spark.sparkContext.textFile("F:\\Files\\WordCount.txt")
// 文章中的单词都是以空格分隔的,
// flatMap函数的作用就是对文件中的每一行单词以空格来分隔,
// 得到是摊平的每个独立的单词, 如果打印出来的话就是每行一个单词。
val words = lines.flatMap(_.split(" "))
// 将每个单词转换成key-value对, value都是1,
// 例如:spark 转换成 (spark, 1)。
val ones = words.map(m => (m, 1))
// 根据key进行聚合, 对于相同的key, 将其对应的value相加。
val counts = ones.reduceByKey(_ + _)
// 打印结果, 可以看到文件中每个单词的个数
counts.foreach(f => {
println(f._1 +": "+ f._2)
})
// 或者也可以保存到一个文件中。
//counts.coalesce(1).saveAsTextFile("F:\\Files\\WordCountResult.txt")
// 关闭SparkSession
spark.close()
}
}
Python版本
# -*- coding: utf-8 -*-
from pyspark.sql import SparkSession
from operator import add
if __name__ == '__main__':
spark = SparkSession\
.builder\
.appName("python word count")\
.master('local[4]')\
.getOrCreate()
lines = spark.sparkContext.textFile('F:\\Files\\WordCount.txt')
# lambda函数以空格分隔每行单词
words = lines.flatMap(lambda x: x.split(' '))
# Python中也是元组Tuple
ones = words.map(lambda x: (x, 1))
# 需要用到add这个求和函数
counts = ones.reduceByKey(add)
# 打印结果
counts.foreach(lambda x: print(str(x[0]) + ': ' + str(x[1])))
spark.stop()
Java版本
import org.apache.spark.api.java.JavaPairRDD;
import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.sql.SparkSession;
import scala.Tuple2;
import java.util.Arrays;
public class JavaWordCount {
public static void main(String[] args) {
SparkSession spark = SparkSession
.builder()
.appName("JavaWordCount")
.master("local[4]")
.getOrCreate();
JavaRDD<String> lines = spark.sparkContext()
.textFile("F:\\Files\\WordCount.txt", 2) //要给一个分区数
.toJavaRDD();
// 以空格分隔每行单词
JavaRDD<String> words = lines
.flatMap(s -> Arrays.asList(s.split(" ")).iterator());
// 将每个单词转换成元组Tuple(其实就是key-value对)
JavaPairRDD<String, Integer> ones = words.mapToPair(s -> new Tuple2<>(s, 1));
// 以key聚合求值
JavaPairRDD<String, Integer> counts = ones.reduceByKey((i1, i2) -> i1 + i2);
// 打印结果
counts.foreach(f -> System.out.println(f._1 +": "+ f._2));
spark.stop();
}
}