spark中RDD的转化操做和行动操做

2019年12月07日 阅读数:81
这篇文章主要向大家介绍spark中RDD的转化操做和行动操做,主要内容包括基础应用、实用技巧、原理机制等方面,希望对大家有所帮助。

本文主要是讲解spark里RDD的基础操做。RDD是spark特有的数据模型,谈到RDD就会提到什么弹性分布式数据集,什么有向无环图,本文暂时不去展开这些高深概念,在阅读本文时候,你们能够就把RDD看成一个数组,这样的理解对咱们学习RDD的API是很是有帮助的。本文全部示例代码都是使用scala语言编写的。html

  Spark里的计算都是操做RDD进行,那么学习RDD的第一个问题就是如何构建RDD,构建RDD从数据来源角度分为两类:第一类是从内存里直接读取数据,第二类就是从文件系统里读取,固然这里的文件系统种类不少常见的就是HDFS以及本地文件系统了。java

  第一类方式从内存里构造RDD,使用的方法:makeRDD和parallelize方法,以下代码所示:shell

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/* 使用makeRDD建立RDD */
/* List */
val  rdd 01  =  sc.makeRDD(List( 1 , 2 , 3 , 4 , 5 , 6 ))
val  r 01  =  rdd 01 .map { x  = > x * x }
println(r 01 .collect().mkString( "," ))
/* Array */
val  rdd 02  =  sc.makeRDD(Array( 1 , 2 , 3 , 4 , 5 , 6 ))
val  r 02  =  rdd 02 .filter { x  = > x <  5 }
println(r 02 .collect().mkString( "," ))
 
val  rdd 03  =  sc.parallelize(List( 1 , 2 , 3 , 4 , 5 , 6 ),  1 )
val  r 03  =  rdd 03 .map { x  = > x +  1  }
println(r 03 .collect().mkString( "," ))
/* Array */
val  rdd 04  =  sc.parallelize(List( 1 , 2 , 3 , 4 , 5 , 6 ),  1 )
val  r 04  =  rdd 04 .filter { x  = > x >  3  }
println(r 04 .collect().mkString( "," ))

 

  你们看到了RDD本质就是一个数组,所以构造数据时候使用的是List(链表)和Array(数组)类型。apache

  第二类方式是经过文件系统构造RDD,代码以下所示:windows

1
2
3
val  rdd : RDD[String]  =  sc.textFile( "file:///D:/sparkdata.txt" 1 )
val  r : RDD[String]  =  rdd.flatMap { x  = > x.split( "," ) }
println(r.collect().mkString( "," ))

  这里例子使用的是本地文件系统,因此文件路径协议前缀是file://。数组

  构造了RDD对象了,接下来就是如何操做RDD对象了,RDD的操做分为转化操做(transformation)和行动操做(action),RDD之因此将操做分红这两类这是和RDD惰性运算有关,当RDD执行转化操做时候,实际计算并无被执行,只有当RDD执行行动操做时候才会促发计算任务提交,执行相应的计算操做。区别转化操做和行动操做也很是简单,转化操做就是从一个RDD产生一个新的RDD操做,而行动操做就是进行实际的计算。服务器

  下面是RDD的基础操做API介绍:app

操做类型框架

函数名eclipse

做用

转化操做

map()

参数是函数,函数应用于RDD每个元素,返回值是新的RDD

flatMap()

参数是函数,函数应用于RDD每个元素,将元素数据进行拆分,变成迭代器,返回值是新的RDD

filter()

参数是函数,函数会过滤掉不符合条件的元素,返回值是新的RDD

distinct()

没有参数,将RDD里的元素进行去重操做

union()

参数是RDD,生成包含两个RDD全部元素的新RDD

intersection()

参数是RDD,求出两个RDD的共同元素

subtract()

参数是RDD,将原RDD里和参数RDD里相同的元素去掉

cartesian()

参数是RDD,求两个RDD的笛卡儿积

行动操做

collect()

返回RDD全部元素

count()

RDD里元素个数

countByValue()

各元素在RDD中出现次数

reduce()

并行整合全部RDD数据,例如求和操做

fold(0)(func)

和reduce功能同样,不过fold带有初始值

aggregate(0)(seqOp,combop)

和reduce功能同样,可是返回的RDD数据类型和原RDD不同

foreach(func)

对RDD每一个元素都是使用特定函数

  下面是以上API操做的示例代码,以下:

  转化操做:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
val  rddInt : RDD[Int]  =  sc.makeRDD(List( 1 , 2 , 3 , 4 , 5 , 6 , 2 , 5 , 1 ))
val  rddStr : RDD[String]  =  sc.parallelize(Array( "a" , "b" , "c" , "d" , "b" , "a" ),  1 )
val  rddFile : RDD[String]  =  sc.textFile(path,  1 )
 
val  rdd 01 : RDD[Int]  =  sc.makeRDD(List( 1 , 3 , 5 , 3 ))
val  rdd 02 : RDD[Int]  =  sc.makeRDD(List( 2 , 4 , 5 , 1 ))
 
/* map操做 */
println( "======map操做======" )
println(rddInt.map(x  = > x +  1 ).collect().mkString( "," ))
println( "======map操做======" )
/* filter操做 */
println( "======filter操做======" )
println(rddInt.filter(x  = > x >  4 ).collect().mkString( "," ))
println( "======filter操做======" )
/* flatMap操做 */
println( "======flatMap操做======" )
println(rddFile.flatMap { x  = > x.split( "," ) }.first())
println( "======flatMap操做======" )
/* distinct去重操做 */
println( "======distinct去重======" )
println(rddInt.distinct().collect().mkString( "," ))
println(rddStr.distinct().collect().mkString( "," ))
println( "======distinct去重======" )
/* union操做 */
println( "======union操做======" )
println(rdd 01 .union(rdd 02 ).collect().mkString( "," ))
println( "======union操做======" )
/* intersection操做 */
println( "======intersection操做======" )
println(rdd 01 .intersection(rdd 02 ).collect().mkString( "," ))
println( "======intersection操做======" )
/* subtract操做 */
println( "======subtract操做======" )
println(rdd 01 .subtract(rdd 02 ).collect().mkString( "," ))
println( "======subtract操做======" )
/* cartesian操做 */
println( "======cartesian操做======" )
println(rdd 01 .cartesian(rdd 02 ).collect().mkString( "," ))
println( "======cartesian操做======" )

  行动操做代码以下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
val  rddInt : RDD[Int]  =  sc.makeRDD(List( 1 , 2 , 3 , 4 , 5 , 6 , 2 , 5 , 1 ))
val  rddStr : RDD[String]  =  sc.parallelize(Array( "a" , "b" , "c" , "d" , "b" , "a" ),  1 )
 
/* count操做 */
println( "======count操做======" )
println(rddInt.count())
println( "======count操做======" )  
/* countByValue操做 */
println( "======countByValue操做======" )
println(rddInt.countByValue())
println( "======countByValue操做======" )
/* reduce操做 */
println( "======countByValue操做======" )
println(rddInt.reduce((x ,y)  = > x + y))
println( "======countByValue操做======" )
/* fold操做 */
println( "======fold操做======" )
println(rddInt.fold( 0 )((x ,y)  = > x + y))
println( "======fold操做======" )
/* aggregate操做 */
println( "======aggregate操做======" )
val  res : (Int,Int)  =  rddInt.aggregate(( 0 , 0 ))((x,y)  = > (x. _ 1  + x. _ 2 ,y),(x,y)  = > (x. _ 1  + x. _ 2 ,y. _ 1  + y. _ 2 ))
println(res. _ 1  ","  + res. _ 2 )
println( "======aggregate操做======" )
/* foeach操做 */
println( "======foeach操做======" )
println(rddStr.foreach { x  = > println(x) })
println( "======foeach操做======" )

  RDD操做暂时先学习到这里,剩下的内容在下一篇里再谈了,下面我要说说如何开发spark,安装spark的内容我后面会使用专门的文章进行讲解,这里咱们假设已经安装好了spark,那么咱们就能够在已经装好的spark服务器上使用spark-shell进行与spark交互的shell,这里咱们直接能够敲打代码编写spark程序。可是spark-shell毕竟使用太麻烦,并且spark-shell一次只能使用一个用户,当另一个用户要使用spark-shell就会把前一个用户踢掉,并且shell也没有IDE那种代码补全,代码校验的功能,使用起来非常痛苦。

  不过spark的确是一个神奇的框架,这里的神奇就是指spark本地开发调试很是简单,本地开发调试不须要任何已经装好的spark系统,咱们只须要创建一个项目,这个项目能够是java的也能够是scala,而后咱们将spark-assembly-1.6.1-hadoop2.6.0.jar这样的jar放入项目的环境里,这个时候咱们就能够在本地开发调试spark程序了。

  你们请看咱们装有scala插件的eclipse里的完整代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
package  cn.com.sparktest
 
import  org.apache.spark.SparkConf
import  org.apache.spark.SparkConf
import  org.apache.spark.SparkContext
import  org.apache.spark.rdd.RDD
 
object  SparkTest {
   val  conf : SparkConf  =  new  SparkConf().setAppName( "xtq" ).setMaster( "local[2]" )
   val  sc : SparkContext  =  new  SparkContext(conf)
   
   /**
    * 建立数据的方式--从内存里构造数据(基础)
    */
   def  createDataMethod() : Unit  =  {
     /* 使用makeRDD建立RDD */
     /* List */
     val  rdd 01  =  sc.makeRDD(List( 1 , 2 , 3 , 4 , 5 , 6 ))
     val  r 01  =  rdd 01 .map { x  = > x * x }
     println( "===================createDataMethod:makeRDD:List=====================" )
     println(r 01 .collect().mkString( "," ))
     println( "===================createDataMethod:makeRDD:List=====================" )
     /* Array */
     val  rdd 02  =  sc.makeRDD(Array( 1 , 2 , 3 , 4 , 5 , 6 ))
     val  r 02  =  rdd 02 .filter { x  = > x <  5 }
     println( "===================createDataMethod:makeRDD:Array=====================" )
     println(r 02 .collect().mkString( "," ))
     println( "===================createDataMethod:makeRDD:Array=====================" )
     
     /* 使用parallelize建立RDD */
     /* List */
     val  rdd 03  =  sc.parallelize(List( 1 , 2 , 3 , 4 , 5 , 6 ),  1 )
     val  r 03  =  rdd 03 .map { x  = > x +  1  }
     println( "===================createDataMethod:parallelize:List=====================" )
     println(r 03 .collect().mkString( "," ))
     println( "===================createDataMethod:parallelize:List=====================" )
     /* Array */
     val  rdd 04  =  sc.parallelize(List( 1 , 2 , 3 , 4 , 5 , 6 ),  1 )
     val  r 04  =  rdd 04 .filter { x  = > x >  3  }
     println( "===================createDataMethod:parallelize:Array=====================" )
     println(r 04 .collect().mkString( "," ))
     println( "===================createDataMethod:parallelize:Array=====================" )
   }
   
   /**
    * 建立Pair Map
    */
   def  createPairRDD() : Unit  =  {
     val  rdd : RDD[(String,Int)]  =  sc.makeRDD(List(( "key01" , 1 ),( "key02" , 2 ),( "key03" , 3 )))
     val  r : RDD[String]  =  rdd.keys
     println( "===========================createPairRDD=================================" )
     println(r.collect().mkString( "," ))
     println( "===========================createPairRDD=================================" )
   }
   
   /**
    * 经过文件建立RDD
    * 文件数据:
    *    key01,1,2.3
           key02,5,3.7
       key03,23,4.8
       key04,12,3.9
       key05,7,1.3
    */
   def  createDataFromFile(path : String) : Unit  =  {
     val  rdd : RDD[String]  =  sc.textFile(path,  1 )
     val  r : RDD[String]  =  rdd.flatMap { x  = > x.split( "," ) }
     println( "=========================createDataFromFile==================================" )
     println(r.collect().mkString( "," ))
     println( "=========================createDataFromFile==================================" )
   }
   
   /**
    * 基本的RDD操做
    */
   def  basicTransformRDD(path : String) : Unit  =  {
     val  rddInt : RDD[Int]  =  sc.makeRDD(List( 1 , 2 , 3 , 4 , 5 , 6 , 2 , 5 , 1 ))
     val  rddStr : RDD[String]  =  sc.parallelize(Array( "a" , "b" , "c" , "d" , "b" , "a" ),  1 )
     val  rddFile : RDD[String]  =  sc.textFile(path,  1 )
     
     val  rdd 01 : RDD[Int]  =  sc.makeRDD(List( 1 , 3 , 5 , 3 ))
     val  rdd 02 : RDD[Int]  =  sc.makeRDD(List( 2 , 4 , 5 , 1 ))
 
     /* map操做 */
     println( "======map操做======" )
     println(rddInt.map(x  = > x +  1 ).collect().mkString( "," ))
     println( "======map操做======" )
     /* filter操做 */
     println( "======filter操做======" )
     println(rddInt.filter(x  = > x >  4 ).collect().mkString( "," ))
     println( "======filter操做======" )
     /* flatMap操做 */
     println( "======flatMap操做======" )
     println(rddFile.flatMap { x  = > x.split( "," ) }.first())
     println( "======flatMap操做======" )
     /* distinct去重操做 */
     println( "======distinct去重======" )
     println(rddInt.distinct().collect().mkString( "," ))
     println(rddStr.distinct().collect().mkString( "," ))
     println( "======distinct去重======" )
     /* union操做 */
     println( "======union操做======" )
     println(rdd 01 .union(rdd 02 ).collect().mkString( "," ))
     println( "======union操做======" )
     /* intersection操做 */
     println( "======intersection操做======" )
     println(rdd 01 .intersection(rdd 02 ).collect().mkString( "," ))
     println( "======intersection操做======" )
     /* subtract操做 */
     println( "======subtract操做======" )
     println(rdd 01 .subtract(rdd 02 ).collect().mkString( "," ))
     println( "======subtract操做======" )
     /* cartesian操做 */
     println( "======cartesian操做======" )
     println(rdd 01 .cartesian(rdd 02 ).collect().mkString( "," ))
     println( "======cartesian操做======" )   
   }
   
   /**
    * 基本的RDD行动操做
    */
   def  basicActionRDD() : Unit  =  {
     val  rddInt : RDD[Int]  =  sc.makeRDD(List( 1 , 2 , 3 , 4 , 5 , 6 , 2 , 5 , 1 ))
     val  rddStr : RDD[String]  =  sc.parallelize(Array( "a" , "b" , "c" , "d" , "b" , "a" ),  1 )
     
     /* count操做 */
     println( "======count操做======" )
     println(rddInt.count())
     println( "======count操做======" )  
     /* countByValue操做 */
     println( "======countByValue操做======" )
     println(rddInt.countByValue())