一、spark的算子分类

  转换算子和行动算子

  转换算子:在使用的时候,spark是不会真正执行,直到需要行动算子之后才会执行。在spark中每一个算子在计算之后就会产生一个新的RDD。

二、在编写spark程序的时候,会遇到可以通过spark算子完成的操作,同时,scala原生语法也可以完成的操作是,两者的区别是什么?

  scala在执行语句的时候是在JVM进程执行,所有的计算全是在JVM中通过相应的调度完成。
  而spark的RDD执行时,是通过分布式计算的方式完成。

三、转换算子的使用

map算子:
object suanziTest {
def main(args: Array[String]): Unit = {
val conf = new SparkConf().setAppName("sparkTest").setMaster("local")
val sc = new SparkContext(conf)
val maprdd: RDD[Int] = sc.makeRDD(1.to(10))
//方式一:spark
// val result = maprdd.map(_*10)
// result.foreach(println(_))
// sc.stop()
//方式二:scala
val ints = maprdd.collect()
var result=for( x <- ints) yield (x*10)
result.foreach(println(_))
}
}
filter算子:
根据条件返回符合条件的数据,并生成一个新的RDD
val conf = new SparkConf().setAppName("sparkTest").setMaster("local")
val sc = new SparkContext(conf)
val maprdd: RDD[Int] = sc.makeRDD(1.to(10))
val unit = maprdd.filter(_%2==0)
unit.foreach(println(_))
比如有一个集合,元素值是1到10,将偶数拿出来对集合中的数值进行同一乘以10
maprdd.filter(_%2==0).map(_*10).foreach(println(_))
flatMap算子:
将函数体中计算之后的集合对象,打散(压平)
val strings = Array("hello java","hello scala")
val unit: RDD[String] = sc.makeRDD(strings)
//将一行的数据转为一个元素
val unit1: RDD[String] = unit.flatMap(_.split(" "))
//将一行的数据转为一个数组
val unit2: RDD[Array[String]] = unit.map(_.split(" "))
groupByKey算子:
将相同Key的值放在同一个序列中(集合的一种)
val data= List(("za",12),("za",45),("dd",13))
val value: RDD[(String, Int)] = sc.makeRDD(data)
val value1: RDD[(String, Iterable[Int])] = value.groupByKey()
value1.map(x=>{
var sum:Int=0
for(v <- x._2){
sum+=v
}
//(x._1,sum)
x._1+" "+sum
}).foreach(println(_))
//foreach(x=>println(x._1+" "+x._2))
sc.stop()
}
reduceByKey算子:
将相同的key的值,进行计算之后统一返回
//前面一个下划线表示的是,每一次叠加之后的结果
val data= List(("za",12),("za",45),("dd",13))
val value: RDD[(String, Int)] = sc.makeRDD(data)
value.reduceByKey(_+_).foreach(println(_))
达到的效果和groupByKey一样
union算子:
如果有多个Rdd可以将多个Rdd合并成一个,将后面的rdd的元素,追加到原来的元素,并生成一个新的RDD
var dataA=List(("zs",30),("zs",50),("ls",30))
var dataB=List(("zs",111),("zs",2222),("ls",3333))
//将基础数据转为RDD
val rddA: RDD[(String, Int)] = sc.makeRDD(dataA)
val rddB: RDD[(String, Int)] = sc.makeRDD(dataB)
val value: RDD[(String, Int)] = rddA.union(rddB)
value.foreach(println(_))
join算子:
也是发生在两个rdd之上的。其原理与sql中的inner join一致
将RDDA中的第一个元素拿出来,和RDDB的第一个元素进行匹配,如果KEY相同的话将会组合成一个新的RDD元素(key,(value1,value2))
如果RDDA中有一个元素在RDDB中没有一个匹配的话,将会出现什么结果?
没有匹配的话将不会显示出来,等于mysql中的inner join方式
var dataA=List(("zs",30),("zs",50),("ls",30),("ww",100))
var dataB=List(("zs",111),("zs",2222),("ls",3333),("zl",3000))
//将基础数据转为RDD
val rddA: RDD[(String, Int)] = sc.makeRDD(dataA)
val rddB: RDD[(String, Int)] = sc.makeRDD(dataB)
val value: RDD[(String, (Int, Int))] = rddA.join(rddB)
value.foreach(println(_))
结果:
(ls,(30,3333))
(zs,(30,111))
(zs,(30,2222))
(zs,(50,111))
(zs,(50,2222))
mapValues算子:
对一个map类型中的value值进行统一操作
var dataA=List(("zs",30),("zs",50),("ls",30),("ww",100))
一、//sc.makeRDD(dataA).map(x=>(x._1,x._2*10)).foreach(println(_))
二、sc.makeRDD(dataA).mapValues(_*10).foreach(println(_))
partitionBy算子:
如果有自定义分区的需求的话,可以采用该方式进行处理
如果只需要改变分区的数量的话,有没有必要做自定义分区?
可以采用repartiton(3)算子来进行处理,3为分区数

如何做自定义分区?
1、创建自定义分区类
import org.apache.spark.Partitioner
  class MyPartition(val numPartition:Int) extends Partitioner{
  //定义有多少个分区
  override def numPartitions = {
  numPartition;
  }

  //定义分区的规则
override def getPartition(key: Any) = {
  val values: String = key.toString
  if(values.startsWith("135")){
    0
  }else{
    1
  }
  }
}

2、object suanziTest {
  def main(args: Array[String]): Unit = {
    val conf = new SparkConf().setAppName("sparkTest").setMaster("local")
    val sc = new SparkContext(conf)
    var dataA=List(("zs",30),("zs",50),("ls",30),("ww",100))
    //原来分区
    println( sc.makeRDD(dataA).getNumPartitions)
    //使用自定义分区
    val partiton = new MyPartiton(2)
    println(sc.makeRDD(dataA).partitionBy(partiton).getNumPartitions)
    sc.makeRDD(dataA).partitionBy(partiton).foreach(println(_))
    sc.stop()
  }
}

四、行动算子的使用

对于spark来说,当遇到行动算子的时候,才算是真正开始执行。

count:
统计RDD中有多少个元素
println(sc.makeRDD(dataA).count())
collect:将RDD转为scala中的数组
val value: RDD[Int] = sc.makeRDD(dataA)
val ints: Array[Int] = value.collect()
注:有时候在传递参数的时候,人家要求要一个数组,而自己手里面只有一个RDD的时候,就可以采用这种方式【相当于一种特殊的类型转换】
reduce:
与scala中reduce一样,要求的格式不是一个key、value结构
对于用于reduce算子的,只能有值,spark中的reduce没有类型上的要求
val data = 1.to(10)
val unit = sc.makeRDD(data)
println(unit.reduce(_ + _))
lookup:
要求的RDD类型必须是一个key、value类型
val strings = List("za","ds","fd")
val unit = sc.makeRDD(strings)
//将元素转换为元组,并从RDD中找到key为za的元素
val ints = unit.map((_,1)).lookup("za")
ints.foreach(println(_))
或者:unit.map((_,1)).foreach(x=>{
if(x._1.equals("za")){
println(x._2)
}
})
或者 val va: RDD[(String, Int)] = unit.map((_,1)).filter(_._1.equals("za"))
va.map((_._2)).foreach(println(_))
问题:lookup和直接使用foreach的区别是什么?

foreach的方式:拿出每一个元素,通过if条件的方式进行比较,适合条件的进行输出,
而lookup针对于多个分区的时候,会先将需要查询的值(如"za"先进行分区计算--可以定位za具体在哪一个分区中)那么查询该值的时候,就只需要从该分区中拿到值。
相同之处:如果一个RDD只有一个分区的时候,那么foreach等于lookup的操作,如果多条件查询的话,lookup会需要进行多次的分区操作,而foreach只需要进行一次

sortBy:排序
val tuples = sc.makeRDD(Array(("cc",12),("bb",32),("cc",22),("aa",18),("bb",16),("dd",16),("ee",54),("cc",1),("ff",13),("gg",32),("bb",4)))
// 统计key出现的次数
val counts = tuples.reduceByKey(_+_)
// 按照value进行降序排序
val sorts = counts.sortBy(_._2,false).foreach(println(_))
val unit = 1.to(10)
sc.makeRDD(unit).sortBy(x=>x,false).foreach(println(_))
take算子:
取出rdd中的前三个元素
sc.makeRDD(dataA).sortBy(x=>x,false).take(3).foreach(println(_)) take(3)表示取出RDD的前三个元素 sortBy(x=>x,false)排序
first算子:
等于take(1) 拿出rdd的第一个元素
tuples.first()
saveAsTextFile:
将结果输出到指定的目录中
val unit = 1.to(10)
sc.makeRDD(unit).saveAsTextFile("d:/out")
saveAsSequenceFile(序列化文件):
将结果输出到指定的目录中,而且文件的类型为SequenceFile 要求为 RDD的元素必须由key-value对组成
sc.makeRDD(unit).map((_,1)).saveAsSequenceFile("D:/OUT") map((_,1))转为key-value形式

Spark算子使用的更多相关文章

  1. (转)Spark 算子系列文章

    http://lxw1234.com/archives/2015/07/363.htm Spark算子:RDD基本转换操作(1)–map.flagMap.distinct Spark算子:RDD创建操 ...

  2. Spark算子总结及案例

    spark算子大致上可分三大类算子: 1.Value数据类型的Transformation算子,这种变换不触发提交作业,针对处理的数据项是Value型的数据. 2.Key-Value数据类型的Tran ...

  3. UserView--第二种方式(避免第一种方式Set饱和),基于Spark算子的java代码实现

      UserView--第二种方式(避免第一种方式Set饱和),基于Spark算子的java代码实现   测试数据 java代码 package com.hzf.spark.study; import ...

  4. UserView--第一种方式set去重,基于Spark算子的java代码实现

    UserView--第一种方式set去重,基于Spark算子的java代码实现 测试数据 java代码 package com.hzf.spark.study; import java.util.Ha ...

  5. spark算子之DataFrame和DataSet

    前言 传统的RDD相对于mapreduce和storm提供了丰富强大的算子.在spark慢慢步入DataFrame到DataSet的今天,在算子的类型基本不变的情况下,这两个数据集提供了更为强大的的功 ...

  6. Spark算子总结(带案例)

    Spark算子总结(带案例) spark算子大致上可分三大类算子: 1.Value数据类型的Transformation算子,这种变换不触发提交作业,针对处理的数据项是Value型的数据. 2.Key ...

  7. Spark算子---实战应用

    Spark算子实战应用 数据集 :http://grouplens.org/datasets/movielens/ MovieLens 1M Datase 相关数据文件 : users.dat --- ...

  8. spark算子集锦

    Spark 是大数据领域的一大利器,花时间总结了一下 Spark 常用算子,正所谓温故而知新. Spark 算子按照功能分,可以分成两大类:transform 和 action.Transform 不 ...

  9. Spark:常用transformation及action,spark算子详解

    常用transformation及action介绍,spark算子详解 一.常用transformation介绍 1.1 transformation操作实例 二.常用action介绍 2.1 act ...

随机推荐

  1. PyQt(Python+Qt)学习随笔:invisibleRootItem方法访问QTreeWidget树型部件的隐形根节点

    老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 我们知道在数据结构上来说,任何树都是有根节点的,但我们在QTreeWidget对象中并没有看到界面上 ...

  2. 第11.17节 Python 正则表达式扩展功能:命名组功能及组的反向引用

    一. 引言 在<第11.16节 Python正则元字符"()"(小括号)与组(group)匹配模式>介绍了组匹配模式,在一个正则表达式内可以定义多个组,每个组都有一个顺 ...

  3. PyQt(Python+Qt)学习随笔:QListWidget获取指定行对应项的item()方法

    老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 在列表部件中,可以通过item方法获取指定行对应的项,语法如下: QListWidgetItem i ...

  4. Hello TLM

    前言 目标 了解TLM程序的基本过程.TLM的英文全称是Transaction Level Modeling,中文翻译为事务级建模.它是在SystemC基础上的一个扩展库. 功能描述 模块A向模块B发 ...

  5. js实现刮刮卡抽奖

    刮刮卡抽奖是前端活动页常见的功能: 链接:图像擦除插件(下载及教程讲解)    推荐理由:无缝刮痕,兼容性好,上手简单   插件有些要修改的地方,打开图像擦除插件后可以看下方网友讨论,或者直接下载本博 ...

  6. Android之window机制token验证

    前言 很高兴遇见你~ 欢迎阅读我的文章 这篇文章讲解关于window token的问题,同时也是Context机制和Window机制这两篇文章的一个补充.如果你对Android的Window机制和Co ...

  7. 冬季里有温度的 3D 可视化智慧供热系统

    前言 随着供暖季来临,我国北方大部分省市开始陆续供热.一年一度的供暖问题被提上了日程.在我们的印象里,供热的设施不论是锅炉.管道还是暖气片,都是坚硬的钢铁.铸铁.HT 通过自主研发的强大的基于 HTM ...

  8. 从零到一快速搭建个人博客网站(域名备案 + https免费证书)(一)

    环境介绍 资源 说明 centos v7.2 docker 快速部署项目环境 nginx 反向代理,同时配置https证书 halo v1.4.2,开源博客项目 Let's Encrypt 免费证书 ...

  9. 2020-2021-1 20209307《Linux内核原理与分析》第三周作业

    一.计算机的三大法宝 存储程序计算机.函数调用堆栈机制.中断机制 二.堆栈 堆栈的作用:记录函数调用框架.传递函数参数.保存返回值的地址.提供局部变量存储空间 堆栈操作:push栈顶地址减少四个字节. ...

  10. PHP基础再练习

    一.变量 字母 char , string 类型 数字 int,float类型 数组: 需要注意的是 1.变量名 区分大小写 2.数字不能当变量名开头 echo "var_dump就相当于 ...