Spark(七) -- Scala快速入门
Scala作为Spark的开发语言,想要成为Spark高手,精通Scala是必须要走的一条路
然后一门语言并不是你想精通就能够精通的,更何况是Scala这种面向对象又面向函数的编程语言,个人觉得其学习的门槛会比C#,Java等面向对象语言要高
所以,这篇文章是建立在有一点编程语言知识的基础上的(如学过C#或者Java等),其实所有语言都是大同小异的,学会了一门语言在学其他的就不会像刚开始那么吃力了,因为它们很多概念都是相通的
本篇文章主要是介绍Scala本身的一些特性,以便以能够快速的上手开发,而对于真正要精通Scala,显然要付出的努力还要很多
安装Scala的开发环境就不具体介绍了,请自行百度之。IDE使用的是Eclipse For Scala,下载地址:
Eclipse For Scala
本文大概从以下几个方面来介绍Scala:
- 声明变量的关键字
- 方法的定义格式
- 条件表达式
- 默认参数,带名参数和变长参数
- lazy变量
- 数组
- Map操作
- 元组
- 值函数
- 匿名函数
- 函数柯里化
- 高阶函数示例
- List序列
- case class和模式匹配
Scala中声明变量的关键字只有两种:
val和var,分别表示常量和变量的声明(在Scala提倡中尽量使用val而不是var)
方法的定义格式:
def 方法名(参数名:参数类型,…):返回值类型={方法体}
如:
def add(x:Int,y:Int):Int={ x + y }
定义了一个参数为两个Int类型,返回值也为Int类型的方法add,返回x+y的值
相信已经有人注意到了,在Scala中,每个句子是不用以分号结束的(当然加上分号也没事),而且方法中不用return来返回,默认返回的是最后一行的值
当方法没有返回值时表现形式为:
def add():Unit={...}
或者直接省略:Unit
def add()={...}
在调用方法的时候,如果该方法没有参数,可以省略括号,如:
add//加上括号也没事,如add()
条件表达式:
和其他语言的if/else唯一的却别就是,Scala的if/else是有返回值的
val x = 8 val res = if(x > 7) 1 else 0
如果x>7就返回1,否则返回0,赋值给res
Scala中的while和do-while用法是和其他语言一样的,但是for的用法就不同了
for循环语句的格式为:
for(i <- 表达式){ 循环体 }
例如:
for(i <- 1 to 10){ println(i) }
上面代码中,1 to 10会产生1-10中的每个数,i会迭代循环这10个数,迭代一次执行一次循环体。
刚开始看肯定会很奇怪,<-这个符号是必须的,现在假设我们有一个arr数组,里面有1-10这10个数
首先用C#的循环方式为:
for(int i = 0;i < arr.Length;i++) { Console.WriteLine(arr[i]); } //或者foreach方式 foreach(var i in arr) { Console.WriteLine(i); }
在对比一下Scala的for循环:
for(i <- 0 to arr.length){ println(arr[i]) } //for同时也可以当foreach使用 for(i <- arr){ println(i) }
并且,在Scala中,for循环是可以添加if判断语句的,如:
for(i <- 0 to 10 if i % 2 == 0){ println(i) }
上面代码的意思是,循环0-10,只打印出偶数
Scala的循环表达式中没有continue和break语句,但是可以通过一个Boolean变量和嵌套函数中return来实现
默认参数,带名参数和变长参数:
这几个概念很简单,通过几行实例代码基本可以了解
默认参数:
def getName(name:String = "JChubby") = {...}
调用getName时如果没有传参数,则会使用默认的JChubby
带名参数:
def showNum(x:Int,y:Int):Unit = {...}
调用该方法时,参数可以不按顺序,但是要执行参数名:
showNum(y = 2,x = 4)
变长参数:
def canChangeLength(x:Int*) = {...}
调用时:
canChangeLength(1,2,3,4,...)
lazy变量:
正常情况下使用val或者var声明变量时是直接分配内存空间使用的
当使用lazy关键字时,这个常/变量只有在使用的时候才会被分配内存
如在Scala命令行中输入下面的代码之后回车:
lazy val a = 1
lazy(懒值)对应开销很大的初始化操作非常有用,如在读取一个很大的文件的时候,如果一开始并不马上使用,可以将其标记为lazy,直到文件真正使用的时候才分配内存空间
数组:
Scala中分为两种:
定长数组:scala.collection.immutable.Array,一旦声明之后长度不可变
变长数组:scala.collection.mutable.ArrayBuffer,动态数组
定长数组使用:
val arr = new Array[Int](3)//声明长度为3,类型为Int的Array数组(new可省略) //或者声明时直接赋值 //编译器会自动推断类型为Int val arr = Array(1,2,3) //通过下标访问数组的方式为()而不是[],请注意! val a = arr(0)
变长数组使用:
val arrBuf = scala.collection.mutable.ArrayBuffer[Int]() //添加元素,相当于add arrBuf += 1 //也可以一次性添加多个 arrBuf += (1,2,3) //使用++=可以直接添加一个数组 arrBuf ++= Array(1,2,3) //在指定位置插入若干个元素,在0位置插入1,2,3 arrBuf.insert(0,1,2,3) //Scala中的函数除了通过.来调用之外也可以直接写成一下形式 arrBuf insert (0,1,2,3) //之前的1 to 10 其实就是调用了1.to(10)这个to方法 //移除指定位置的元素 arrBuf remove 0 //移除指定位置后的连续n个元素 arrBuf remove 0,3 //删除末尾的n个元素 arrBuf trimEnd 3
此外还有例如min,max等函数求最大最小等常用操作
Map操作:
和数组一样,Map同样也分为可变和不可变两种
不可变Map的使用:
//声明一个Map,包含两个键值对,->表示键值对应的关系 val myMap = Map("JChubby" -> 22,"Looky" -> 21)
不可变的Map中,一旦声明之后,该Map不可添加不可删除不可修改,只能查看,查看方式与可变Map一致
可变Map的使用:
val myMap = scala.collection.mutable.Map("JChubby" -> 22,"Looky" -> 21) //添加元素 myMap += ("abc" -> 12,"bcd" -> 13) //删除元素 myMap -= "abc" //修改元素 myMap("JChubby") = 10 //或者 myMap += ("JChubby" -> 10) //查找元素 myMap("JChubby") //或者使用getOrElse,该方法在取不到值的时候返回一个默认值,以免出现异常 myMap getOrElse ("JChubby",-1) //遍历,使用的是k,v格式来进行遍历 for((k,v) <- myMap){ println(k + ":" + v) } //如果只要遍历k或者v,可以使用_占位符 for((k,_) <- myMap){ println(k) } //获取所有的key myMap.keySet //获取所有的value myMap.values
元组:
元组其实就是一个集合,但是可以存放各种不同类型的数据
例如:
val group = (1,2,"JChubby",3.0) //通过下标访问元组的格式为:元组名._下标 或者 元组名 _下标。如: group._0 group _0 //遍历元组格式为,productIterator为固定格式不可少 for(element <- group.productIterator){ ... }
值函数:
Scala中可以将函数赋值给一个变量,这个变量就称为值函数
def add(x:Int,y:Int):Int = { x + y } //格式为方法名+空格+_ var res = add _ //之后可以将这个变量当做方法来用 res(1,2)
匿名函数:
顾名思义,没有名字的函数,定义格式如下:
(参数名:参数类型,…) => 表达式
例如:
(x:Int) => x + 3
可以将匿名函数赋值给一个常量
val func = (x:Int) => x + 3 //直接调用常量 func(7)
上面的用法其实和直接定义一个有名的函数是一样的,匿名函数主要是当做函数的参数来传递使用
例如scala.collection.mutable.ArrayBuffer的map方法,其参数要求是一个匿名函数
scala.collection.mutable.ArrayBuffer.map((x:Int) => x +3)
执行的结果是ArrayBuffer里面每个值都加3(map函数之后会介绍)
函数柯里化:
函数柯里化就是将原本有 很多参数 的函数,分成一个个只有 一个参数 的函数,每个函数的返回值都是 一个表达式 并且当做参数 传到下一个函数
例如:
def mul(x:Int,y:Int) = x + y //调用方式为 mul(1,2) //柯里化后的函数为 def mul(x:Int)(y:Int) = x + y //调用当时为 mul(1)(2) //执行mul(1)时,返回的是1 + y,在将这个函数应用到2,得到 1 + 2
柯里化是闭包的典型体现,具体柯里化的概念请百度之~
高阶函数示例:
数组的map函数
val arr = Array(1,2,3) arr.map(1 + _)
_表示数组中的每个元素,执行的结果为每个元素+1
数组的filter函数
arr.filter(_ > 2)
_ > 2会将数组中大于2的元素过滤出来
数组的reduce函数
arr.reduce(_ + _)
reduce是迭代运算,将数组中两个元素先执行操作,把结果作为一个元素继续和下一个元素进行操作,执行结果为:1+2=3,3+3=9,也就是求和
List序列:
List操作:
val list = List(1,2,3) //获取头元素 list.head //获取除了头元素之外的其他元素 list.tail //新增元素 7::list //注意,::运算符是从右向左的 //获取前n个元素 list.take(n) //list的zip操作 val list1 = List(a,b,c) list.zip(list1) //得到的结果为List((1,a),(2,b),(3,c)),如果两个list的长度不同,以比较短的为基础 //flatten操作 val list2 = List(List(1,2),List(2,3),List(3,4)) list2.flatten //得到的结果为List(1,2,2,3,3,4),用于将嵌套List组合成一个新的List //flatmap操作 list2.flatmap(_.map(_ * 2)) //跟flatten相比,flatmap在组合之前,会先对每个子List进行map操作
case class和模式匹配:
case class又称为样例类,和普通的类相比,样例类不用new就可以实例化,默认执行的是apply方法来构造对象
模式匹配:
和其他语言的switch功能差不多,但是Scala里面使用的是match
使用示例:
val res = 1 res match{ case 0 => println(0) case 1 => println(1) case 2 => println(2) }
除了用法格式上略有不同,其余的基本类似,并且不需要使用break关键字
样例类和模式匹配结合使用:
//定义抽象类Human abstract class Human //分别定义用例类Chinese,Japanese,American都继承自Human case class Chinese(name:String) extends Human case class Japanese(name:String) extends Human case class American(name:String) extends Human //定义模式匹配方法 def caseMatch(human:Human){ //human参数类型不同,做出不同处理,Chinese(_)表示只关心是不是Chinese而不关心叫什么名字 case Chinese(_) => println("Chinese") case Japanese(_) => println("Japanese") case American(_) => println("American") }

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
Spark(六) -- Spark计算模型
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq1010885678/article/details/45788083 整个Spark框架都是基于RDD算子来进行计算的。 What is RDD? Resilient Distributed Dataset(RDD),分布式弹性数据集,是Spark上的一个核心抽象 表示用于并行计算的,不可修改的,对数据集合进行分片的数据结构 简单地,可以将RDD看成是Spark平台上的通用货币 在Spark上,针对各种各样的计算场景存在着各种各种的RDD,这些RDD拥有一些共同的操作,例如map,filter,persist等,就好像RDDs都是一个总RDD的子类一样,拥有所有RDD的共同特性 同时RDDs也拥有能表达自己特性的操作,例如PairRDDR有groupByKey,join等操作,而DoubleRDD有Doubles操作 所有的RDD都有以下特性: 可以表示数据分片的列表集合。将原始数据经过某些分片处理生成RDDs,这些RDD将用于并行计算 通用的算子来计算每个数据分片 包括transf...
- 下一篇
大数据分析的八大趋势
Intuit数据工程副主管Loconzolo双脚都已经迈进数据湖里了。Smarter Remarketer首席数据科学家DeanAbbott也为云技术的发展指出了捷径。他们二人一致认为, 大数据与分析学前沿是个活动目标,这一领域包含了储存原始数据的数据湖和云计算。尽管这些技术并未成熟,但等待也并非上策。 Loconzolo表示:“现实的情况是,这些工具都刚刚兴起,他们构筑的平台还不足以让企业依赖。但是,大数据和分析学等学科发展十分迅速,因此企业必须努力跟上,否则就有被甩掉的危险。”他还说:“过去,新兴技术往往需要十年左右的时间才能够成熟,但是现在大大不同了,人们几个月甚至几周时间就能想出解决方案。”那么,有哪些新兴技术是我们应该关注,或者说科研人员正在重点研究的呢?《电脑世界》采访了一些IT精英、咨询师和行业分析专家,来看看他们列出的几大趋势吧。 1.云端大数据分析 Hadoop是一组有一定框架结构的工具,用来处理大型数据组。它原本用于机器群,但现在情况有所变化。Forrester Research一位分析师BrianHopkins表示,现在有越来越多的技术可以运用到云端数据处理上来了...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- MySQL8.0.19开启GTID主从同步CentOS8
- Docker安装Oracle12C,快速搭建Oracle学习环境
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- CentOS7安装Docker,走上虚拟化容器引擎之路
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- Hadoop3单机部署,实现最简伪集群
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- CentOS8编译安装MySQL8.0.19