一、转换算子
value 类型:
1.1 map 算子
1、算子签名
def map[U: ClassTag](f: T => U): RDD[U]
2、算子说明
将处理的数据逐条进行映射转换,这里的转换可以是类型的转换,也可以是值的转换。
3、代码演示
package spark.core.conversion_operator.map
import org.apache.spark.rdd.RDD
import org.apache.spark.{
SparkConf, SparkContext}
/**
* map 算子介绍
*/
object Spark_RDD_Operator_Map_Study1 {
def main(args: Array[String]): Unit = {
val sparkConf = new SparkConf().
setMaster("local[*]").
set("spark.driver.host", "localhost").
setAppName("rdd")
val sc = new SparkContext(sparkConf)
val rdd: RDD[Int] = sc.makeRDD(List(1, 2, 3, 4))
// 转换:旧 RDD -> 算子 -> 新 RDD
// 简化过程:
// var rdd1: RDD[Int] = rdd.map((i: Int) => {
// i * 2
// })
// var rdd1: RDD[Int] = rdd.map((i: Int) => i * 2)
// var rdd1: RDD[Int] = rdd.map((i) => i * 2)
// var rdd1: RDD[Int] = rdd.map(i => i * 2)
val rdd1: RDD[Int] = rdd.map(_ * 2)
// 读取数据
// collect 方法不回转换 RDD,会触发作业的执行,所以将 collect 这样的方法称为行动算子(action)。
val ints: Array[Int] = rdd1.collect()
for (elem <- ints) {
print(elem + " ")
}
sc.stop()
}
}
运算结果:
4、demo
(1) 说明
从日志数据中获取用户请求 URL 资源路径
(2) 数据
83.149.9.216 - - 17/05/2015:10:05:03 +0000 GET /presentations/logstash-monitorama-2013/images/kibana-search.png
83.149.9.216 - - 17/05/2015:10:05:43 +0000 GET /presentations/logstash-monitorama-2013/images/kibana-dashboard3.png
83.149.9.216 - - 17/05/2015:10:05:47 +0000 GET /presentations/logstash-monitorama-2013/plugin/highlight/highlight.js
83.149.9.216 - - 17/05/2015:10:05:12 +0000 GET /presentations/logstash-monitorama-2013/plugin/zoom-js/zoom.js
83.149.9.216 - - 17/05/2015:10:05:07 +0000 GET /presentations/logstash-monitorama-2013/plugin/notes/notes.js
83.149.9.216 - - 17/05/2015:10:05:34 +0000 GET /presentations/logstash-monitorama-2013/images/sad-medic.png
83.149.9.216 - - 17/05/2015:10:05:57 +0000 GET /presentations/logstash-monitorama-2013/css/fonts/Roboto-Bold.ttf
83.149.9.216 - - 17/05/2015:10:05:50 +0000 GET /presentations/logstash-monitorama-2013/css/fonts/Roboto-Regular.ttf
83.149.9.216 - - 17/05/2015:10:05:24 +0000 GET /presentations/logstash-monitorama-2013/images/frontend-response-codes.png
83.149.9.216 - - 17/05/2015:10:05:50 +0000 GET /presentations/logstash-monitorama-2013/images/kibana-dashboard.png
83.149.9.216 - - 17/05/2015:10:05:46 +0000 GET /presentations/logstash-monitorama-2013/images/Dreamhost_logo.svg
83.149.9.216 - - 17/05/2015:10:05:11 +0000 GET /presentations/logstash-monitorama-2013/images/kibana-dashboard2.png
83.149.9.216 - - 17/05/2015:10:05:19 +0000 GET /presentations/logstash-monitorama-2013/images/apache-icon.gif
83.149.9.216 - - 17/05/2015:10:05:33 +0000 GET /presentations/logstash-monitorama-2013/images/nagios-sms5.png
83.149.9.216 - - 17/05/2015:10:05:00 +0000 GET /presentations/logstash-monitorama-2013/images/redis.png
83.149.9.216 - - 17/05/2015:10:05:25 +0000 GET /presentations/logstash-monitorama-2013/images/elasticsearch.png
83.149.9.216 - - 17/05/2015:10:05:59 +0000 GET /presentations/logstash-monitorama-2013/images/logstashbook.png
83.149.9.216 - - 17/05/2015:10:05:30 +0000 GET /presentations/logstash-monitorama-2013/images/github-contributions.png
83.149.9.216 - - 17/05/2015:10:05:53 +0000 GET /presentations/logstash-monitorama-2013/css/print/paper.css
83.149.9.216 - - 17/05/2015:10:05:24 +0000 GET /presentations/logstash-monitorama-2013/images/1983_delorean_dmc-12-pic-38289.jpeg
83.149.9.216 - - 17/05/2015:10:05:54 +0000 GET /presentations/logstash-monitorama-2013/images/simple-inputs-filters-outputs.jpg
83.149.9.216 - - 17/05/2015:10:05:33 +0000 GET /presentations/logstash-monitorama-2013/images/tiered-outputs-to-inputs.jpg
83.149.9.216 - - 17/05/2015:10:05:56 +0000 GET /favicon.ico
24.236.252.67 - - 17/05/2015:10:05:40 +0000 GET /favicon.ico
93.114.45.13 - - 17/05/2015:10:05:14 +0000 GET /articles/dynamic-dns-with-dhcp/
93.114.45.13 - - 17/05/2015:10:05:04 +0000 GET /reset.css
93.114.45.13 - - 17/05/2015:10:05:45 +0000 GET /style2.css
93.114.45.13 - - 17/05/2015:10:05:14 +0000 GET /favicon.ico
93.114.45.13 - - 17/05/2015:10:05:17 +0000 GET /images/jordan-80.png
93.114.45.13 - - 17/05/2015:10:05:21 +0000 GET /images/web/2009/banner.png
66.249.73.135 - - 17/05/2015:10:05:40 +0000 GET /blog/tags/ipv6
50.16.19.13 - - 17/05/2015:10:05:10 +0000 GET /blog/tags/puppet?flav=rss20
(3) 代码
package spark.core.conversion_operator.map
import org.apache.spark.{
SparkConf, SparkContext}
import org.apache.spark.rdd.RDD
/**
* 使用 map 算子做的一个 demo,处理一下日志数据。
*/
object Spark_RDD_Operator_Map_Demo1 {
def main(args: Array[String]): Unit = {
val sparkConf = new SparkConf().
setMaster("local[*]").
set("spark.driver.host", "localhost").
setAppName("rdd")
val sc = new SparkContext(sparkConf)
// 从日志数据中获取用户请求 URL 资源路径
val fileRDD: RDD[String] = sc.textFile("input/apache.log")
val urlRDD: RDD[String] = fileRDD.map(
line => {
var datas: Array[String] = line.split(" ")
datas(6)
}
)
urlRDD.collect().foreach(println)
sc.stop()
}
}
(4) 运行结果
1.2 mapPartitions 算子
1、算子签名
def mapPartitions[U: ClassTag](
f: Iterator[T] => Iterator[U],
preservesPartitioning: Boolean = false): RDD[U]
2、算子说明
将待处理的数据以分区为单位发送到计算节点进行处理,这里的处理是指可以进行任意的处理,哪怕是过滤数据。
3、代码演示
package spark.core.conversion_operator.mapPartitions
import org.apache.spark.rdd.RDD
import org.apache.spark.{
SparkConf, SparkContext}
/**
* mapPartitions 算子介绍
*/
object Spark_RDD_Operator_MapPartitions_Study1 {
def main(args: Array[String]): Unit = {
val sparkConf = new SparkConf().
setMaster("local[*]").
set("spark.driver.host", "localhost").
setAppName("rdd")
val sc = new SparkContext(sparkConf)
val rdd: RDD[Int] = sc.makeRDD(List(1, 2, 3, 4), numSlices = 2)
// mapPartitions 是以分区作为单位进行计算,和 map 算子很像。
// 区别就在于 map 算子是一个一个执行,而 mapPartitions 一个一个分区执行,类似于批处理。
// map 方法是全量数据操作,不能丢失数据。
// mapPartitions 方法是一次性获取分区的所有数据,那么可以执行迭代器集合的所有操作,
// 比如:过滤、max、sum
val rdd1: RDD[Int] = rdd.mapPartitions(
iter => {
iter.filter(_ % 2 == 0)
}
)
val data: Array[Int] = rdd1.collect()
println(data.mkString(","))
println(data.toList)
sc.stop()
}
}
运算结果:
4、demo
(1) 说明
获取每个数据分区的最大值
(2) 代码
package spark.core.conversion_operator.mapPartitions
import org.apache.spark.{
SparkConf, SparkContext}
import org.apache.spark.rdd.RDD
/**
* mapPartitions 算子获取各个分区的最大值
*/
object Spark_RDD_Operator_MapPartitions_Demo1 {
def main(args: Array[String]): Unit = {
val sparkConf = new SparkConf().
setMaster("local[*]").
set("spark.driver.host", "localhost").
setAppName("rdd")
val sc = new SparkContext(sparkConf)
val rdd: RDD[Int] = sc.makeRDD(List(1, 4, 3, 2, 5, 6), numSlices = 2)
// 获取分区的最大值,第一个分区为 1 4 3,第二个分区为 2 5 6。
val rdd1: RDD[Int] = rdd.mapPartitions(
iter => {
List(iter.max).iterator
}
)
// map 与 mapPartitions 区别:
// map 算子每一次处理一条数据,而 mapPartitions 算子每一次将一个分区的数据当成一个整体
// 进行数据处理,如果一个分区的数据没有完全处理完,那么所有的数据都不会释放,即使当前面已经
// 处理完的数据也不会释放。所以当内存空间足够大时,为了提高效率,推荐使用 mapPartitions
// 算子。
val data: Array[Int] = rdd1.collect()
println(data.mkString(","))
sc.stop()
}
}
(3) 运算结果
1.3 mapPartitionsWithIndex 算子
1、算子签名
def mapPartitionsWithIndex[U: ClassTag](
f: (Int, Iterator[T]) => Iterator[U],
preservesPartitioning: Boolean = false): RDD[U]
2、算子说明
将待处理的数据以分区为单位发送到计算节点进行处理,这里的处理是指可以进行任意的处理,哪怕是过滤数据。在处理时同时可以获取当前分区索引。
3、代码演示
package spark.core.conversion_operator.mapPartitionsWithIndex
import org.apache.spark.{
SparkConf, SparkContext}
import org.apache.spark.rdd.RDD
/**
* mapPartitionsWithIndex 算子介绍
*/
object Spark_RDD_Operator_MapPartitionsWithIndex_Study1 {
def main(args: Array[String]): Unit = {
val sparkConf = new SparkConf().
setMaster("local[*]").
set("spark.driver.host", "localhost").
setAppName("rdd")
val sc = new SparkContext(sparkConf)
val rdd: RDD[Int] = sc.makeRDD(List(5, 2, 3, 4), numSlices = 2)
// 获取每个分区的最大值及分区号
val rdd1: RDD[(Int, Int)] = rdd.mapPartitionsWithIndex(
(index, iter) => {
List((index, iter.max)).iterator
}
)
println(rdd1.collect().mkString(","))
sc.stop()
}
}
运算结果:
4、demo
(1) 说明
获取第二个数据分区的数据
(2) 代码
package spark.core.conversion_operator.mapPartitionsWithIndex
import org.apache.spark.rdd.RDD
import org.apache.spark.{
SparkConf, SparkContext}
/**
* mapPartitionsWithIndex 算子介绍
*/
object Spark_RDD_Operator_MapPartitionsWithIndex_Demo1 {
def main(args: Array[String]): Unit = {
val sparkConf = new SparkConf().
setMaster("local[*]").
set("spark.driver.host", "localhost").
setAppName("rdd")
val sc = new SparkContext(sparkConf)
val rdd: RDD[Int] = sc.makeRDD(List(5, 2, 3, 4), numSlices = 2)
// 获取第二个分区的数据
// Nil是一个空的List,定义为List[Nothing]
val rdd2: RDD[Int] = rdd.mapPartitionsWithIndex(
(index, iter) => {
if (index == 1) {
iter
} else {
// 空集合
Nil.iterator
}
}
)
println(rdd2.collect().mkString(","))
sc.stop()
}
}
(3) 运行结果
1.4 flatMap 算子
1、算子签名
def flatMap[U: ClassTag](f: T => TraversableOnce[U]): RDD[U]
2、算子说明
将处理的数据进行扁平化后再进行映射处理,所以算子也称之为扁平映射。
3、代码演示
package spark.core.conversion_operator.flatMap
import org.apache.spark.{
SparkConf, SparkContext}
import org.apache.spark.rdd.RDD
/**
* flatmap 算子的介绍:
* 将处理的数据进行扁平化后再进行映射处理,所以算子也称之为扁平映射。
*/
object Spark_RDD_Operator_FlatMap_Study1 {
def main(args: Array[String]): Unit = {
val sparkConf = new SparkConf().
setMaster("local[*]").
set("spark.driver.host", "localhost").
setAppName("rdd")
val sc = new SparkContext(sparkConf)
val rdd: RDD[List[Int]] = sc.makeRDD(List(List(1, 2), List(3, 4)))
// flatmap() 是将函数应用于 RDD 中的每个元素,将返回的迭代器的所有内容构成新的 RDD。
val rdd1: RDD[Int] = rdd.flatMap(
list => list
)
println(rdd1.collect().mkString(","))
sc.stop()
}
}
运行结果:
4、demo
(1) 说明
对 List(List(1, 2), 3, List(4, 5)) 进行 flatMap
(2) 代码
package spark.core.conversion_operator.flatMap
import org.apache.spark.rdd.RDD
import org.apache.spark.{
SparkConf, SparkContext}
/**
* flatmap 算子的介绍:
* 将处理的数据进行扁平化后再进行映射处理,所以算子也称之为扁平映射。
*/
object Spark_RDD_Operator_FlatMap_Demo1 {
def main(args: Array[String]): Unit = {
val sparkConf = new SparkConf().
setMaster("local[*]").
set("spark.driver.host", "localhost").
setAppName("rdd")
val sc = new SparkContext(sparkConf)
// 将如下数据进行扁平化处理
val rdd1: RDD[Any] = sc.makeRDD(
List(List(