程序入口 SparkContext
val conf = new SparkConf().setMaster("local[2]").setAppName(spark_context")
val sc: SparkContext = new SparkContext(conf)
SparkContext 是 spark-core 的入口组件,是一个 Spark 程序的入口,在 Spark 0.x 版本就已经存在 SparkContext 了,是一个元老级的API
如果把一个 Spark 程序分为前后端,那么服务就是可以运行 Spark 程序的集群,而 Driver 就是 Spark 的前端,
在 Driver 中, SparkContext 是最主要的组件,也是 Driver 在运行时首先会创建的组件,是 Driver 的核心
SparkContext 从提供的 API 来看,主要作用是连接集群,创建 RDD , 累加器,广播变量等
简略的说,RDD 有三种创建方式
?
通过本地集合创建RDD
@Test
def rddCreationLocal(): Unit = {
val seq = Seq("Hello1", "Hello2", "Hello3") // 里面数据是什么类型
val rdd1:RDD[String] = sc.parallelize(seq, 2) // RDD的里面的泛型就是什么类型, 指定为2个分区数
sc.parallelize(seq) // parallelize 可以不指定分区数
val rdd2: RDD[String] = sc.makeRDD(seq,2)
}
通过外部数据创建RDD
@Test
def rddCreationFiles(): Unit = {
sc.textFile("hdfs:///.....")
// 1. textFile中传入的是什么
// * 传入的是一个路径,读取路径
// * hdfs:// file:// /.../...(这种方式分为在集群中执行还是在本地中执行,如果在集群中,读的是hdfs,本地读的是文件系统)
// 2. textFile是否支持分区?
// * 假如传入的path是 hdfs://....
// * 分区是由 HDFS 中文件的 block 决定的
// 3. textFile支持什么平台
// * 支持 aws 和 阿里云
}
通过其它的RDD衍生新的RDD
@Test
def rddCreateFromRDD(): Unit = {
val rdd1 = sc.parallelize(Seq(1, 2, 3))
// 通过在 rdd 上执行算子操作,会生成新的 rdd
// 原地计算
// java中,str.substr 返回新的字符串,非原地计算
// 通过rdd1.map 的操作 ,和字符串中的方式很像, 字符串可变吗?不可变
// RDD 可变吗? 不可变
val rdd2: RDD[Int] = rdd1.map(item => item)
}
map 算子
# spark-shell
sc.parallelize(Seq(1, 2, 3))
.map( num => num * 10)
.collect()
# IDEA
@Test
def mapTest(): Unit = {
// 1. 创建RDD
val rdd1 = sc.parallelize(Seq(1, 2, 3))
// 2. 执行 map 操作
val rdd2 = rdd1.map(item => item * 10)
// 3. 得到结果
val result:Array[Int] = rdd2.collect()
result.foreach(item => println(item))
// 关闭sc
sc.stop()
}
def map[U: ClassTag] (f: T ? U) : RDD[U]
String → Array[String]
则新的 RDD 中每条数据就是一个数组FlatMap算子
# spark-shell
sc.parallelize(Seq("Hello lily", "Hello lucy", "Hello tim"))
.flatMap( line => line.split(" "))
.collect()
# IDEA
@Test
def flatMapTest(): Unit = {
// 1. 创建RDD
val rdd1 = sc.parallelize(Seq("Hello lily", "Hello lucy", "Hello tim"))
// 2. 执行 flatMap 操作
val rdd2 = rdd1.flatMap( line => line.split(" "))
// 3. 得到结果
val result:Array[String] = rdd2.collect()
result.foreach(line => (println(line)))
// 关闭sc
sc.stop()
}*
def flatMap[U: ClassTag](f: T ? List[U]): RDD[U]
f
?→ 参数是原 RDD 数据, 返回值是经过函数转换的新 RDD 的数据, 需要注意的是返回值是一个集合, 集合中的数据会被展平后再放入新的 RDDmap + flatten
, 也就是先转换, 后把转换而来的 List 展开ReduceByKey算子
# spark-shell
sc.parallelize(Seq(("a",1), ("a", 1), ("b", 1)))
.reduceByKey( ( cur, agg) => cur + agg)
.collect()
# IDEA
@Test
def reduceByKeyTest(): Unit = {
// 1. 创建RDD
val rdd1 = sc.parallelize(Seq("Hello lily", "Hello lucy", "Hello tim"))
// 2. 处理数据
val rdd2 = rdd1.flatMap( item => item.split(" "))
.map(item => (item, 1))
.reduceByKey( (cur, agg) => cur + agg)
// 3. 得到结果
val result:Array[(String, Int)] = rdd2.collect()
result.foreach(item => (println(item)))
// 4. 关闭sc
sc.stop()
}
def reduceByKey(func: (V, V) ? V): RDD[(K, V)]