Spark scala api(一)RDD编程

基础

初始化spark

val conf = new SparkConf().setAppName("wordcount")
val sc = new SparkContext(conf)

转化操作和行动操作的区别在于spark计算rdd的方式不同,只有在第一次在一个行动操作中用到转化操作中的rdd时,才会真正计算这些rdd。

创建rdd

// 驱动器程序对一个集合进行并行化
val lines = sc.parallelize(List("pandas","i like pandas"))
//读取外部数据集
val lines = sc.textFile("/path/to/README.md")

rdd操作

  • 转化操作 例如filter()
    filter不会改变已有的inputRDD的数据

    val errorsRDD = inputRDD.filter(line => line.contains(“error”))

  • 行动操作 例如count()

    println("Input had " + badLinesRDD.count() + “concerning lines”)
    println(“Here are 10 examples:”)
    badLinesRDD.take(10).foreach(println)

向spark传递函数

我们可以把定义的内联函数,方法的引用或者静态方法传递给Spark

class SearchFunctions(val query: String){
	def isMatch(s: String):Boolean = {
	 	s.contains(query)
	 	}
	 }
	 //传递整个对象
	 def getMatchesFunctionReference(rdd: RDD[String]) :RDD[String] = {
	 	rdd.map(isMatch)
	 }
	 //传递整个对象
	 def getMatchesFieldReference(rdd: RDD[String]): RDD[String]= {
	 	rdd.map( x => x.split(query))
	 }
	 //传递局部变量
	 def getMatchesNoReference(rdd: RDD[String]: RDD[String] ) = {
	 	val query_ = this.query
	 	rdd.map(x => x.split(query_))

常见转化操作和行动操作

转化操作

  • map(): 接收一个函数,把这个函数作用于RDD中的每一个元素,将函数的返回结果作为结果RDD中对应的值

    val result = input.map( x => x*x)

  • filter():接收一个函数,并将RDD中满足该函数的元素放入新的RDD中返回

    val result = input.filter( x => x.contains(“a”))

  • flatMap():将接收到的函数分别应用到输入RDD中的每一个元素中,返回一个返回值序列的迭代器

    val words = input.flatMap(line => line.spilt(" "))

  • 伪集合操作
    distinct() : RDD中最常缺失的是集合的唯一性,常常有重复的元素,RDD.distinct()转化操作可以生成一个只包含不同元素的新RDD,但是此操作开销很大,需要将所有数据通过网络shuffle。
    union(): 返回一个包含两个RDD中所有元素的RDD,含有重复元素
    intersection():只返回两个RDD中所共有的元素,运行时会去掉所有重复的元素,单个RDD中的重复元素也会去掉,需要shuffle,性能差很多。
    subtract():需要数据混洗,接收一个RDD,并去掉第一个RDD中与接收RDD相同的元素
    cartesian():求笛卡尔积,所有可能的组合

行动操作

  • reduce():接收一个函数作为参数,这个函数要操作两个相同元素类型的RDD数据并返回一个同样类型的新元素
    val sum = rdd.reduce((x,y) => x + y)
  • fold(): 和reduce一样,但是需要提供初始值
  • aggregate():返回值类型可以与所操作的RDD类型不同
    计算RDD的平均值 通过一个函数将RDD中的元素合并起来放入累加器,然后用第二个函数将累加器两两合并
val result = input.aggregate((0,0))(
					(acc , value) => (acc._1 + value ,  acc._2 + 1),
					(acc1, acc2) => (acc._1 +acc2._1, acc1._2 + acc2._2))
val avg = result._1/result._2.toDouble
  • collect()
    collect()将整个RDD的内容返回,将数据复制到驱动器进程中,要求所有数据都能一同放入单台机器的内存中,通常在单元测试中使用
  • take(n)
    返回RDD中的n个元素,不均衡
  • top(n) 如果为数据定义了顺序,可以使用top()从RDD中获取前几个元素,也可以使用自己的比较函数
  • takeSample(withReplacement,num,[seed]) 从RDD返回任意一些元素
  • foreach()
  • count()
  • countByValue()

不同类型RDD之间转化

mean(),variance()只能用在数值RDD,join()只能用在键值对RDD
在scala中,将RDD转为特定函数的RDD是由隐式转换来自动处理的
import org.apache.spark.SparkContext._

持久化

RDD都是惰性求值的
有时需要多次使用同一个RDD
persist()默认会把数据以序列化的形式缓存在JVM的堆空间中
5个级别:MEMORY_ONLY,MEMORY_ONLY_SER,MEMORY_AND_DISK,MEMORY_AND_DISK_SER,DISK_ONLY
import org.apache.spark.storage.StorageLevel
rdd.persist(StorageLevel.DISK_ONLY)
unpersist()手动释放持久化的RDD

你可能感兴趣的:(spark学习)