博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
spark入门之scala学习笔记
阅读量:2456 次
发布时间:2019-05-10

本文共 7697 字,大约阅读时间需要 25 分钟。

之前的基本语法包括循环什么的就不写了,直接从定义函数开始。

一、定义函数

scala中定义函数需要定义函数的名字、参数和函数体。

  • 第一个示例函数:
def sayHello(name:String,age:Int) = {    if (age >= 18) {printf("hi, $s,u r bitch!!!\n",name);age}    else { printf("hi,%s,u r little bitch !!!",name); age    }}

scala 要求给出所有参数的类型,但是不一定要求给出返回值的类型,前提是只要右侧的函数体中不包含递归的语句

  • 单行的函数定义很简单:
def sayHello(name:String) = print("Hello",+name)
  • 多行的代码就可以使用代码块,代码块的最后一行的返回值就是整个函数的返回值,和java不同的是,不使用return返回值
def sum(n:Int) = {    result = 0    for (i <- 1 to n) {    result += i    }    result}
  • 递归函数

与之前函数不同的是,如果在函数体内递归调用函数自身,则必须手动给出函数的返回类型。

示例为斐波那契数列:

def fab(n:Int):Int = {    if (n <= 1 ) 1    else fab(n-1) + fab(n-2)}

二、函数之默认参数和带名参数

示例:

def sayHello(firstname:String,middlename: String = "wiliam",lastname:String = "Bob")=print("hello" + " " + firstname + " " + middlename + " " + lastname)
sayHello("leo",lastname = "jack" ,middlename = "pp")

scala中可以混合使用未命名参数和带名参数,但是未命名参数必须排在带名参数前面。


三、函数之变长参数

在scala中,有时需要将函数定义为参数个数可变的形式,可以使用变长参数定义函数

示例代码:(注意,定义函数中如果没有“=”则无返回值)

def sum(nums:Int*) = {    var result = 0    for (num <- nums) result += num    result}

如果想要将一个已有的序列直接调用变长参数函数,直接使用sum(1 to 5)不可行,此时使用scala特殊的语法将参数定义为序列

重点!!!

val s = sum(1 to 5: _*)

示例:使用递归函数实现累加

def sum2(nums: Int*):Int = {    if (nums.length == 0) 0    else nums.head + sum2(nums.tail: _*)}


四、函数之 过程、lazy值、异常

  • 在scala中,定义函数,如果函数直接包裹在花括号中,而没有使用“=”连接,则函数的返回值类型就是Unit。这样的函数就称为“过程”,过程通常用于不需要返回值的函数。
  • 过程还有一种写法,就是将函数的返回值类型定义为Unit。

示例:

def sayHello(name:String) = "hello " + namedef sayhello(name:String) {print("hello, " + name);"hello, " + name}def sayhello(name:String): Unit = "hello, " + name
  • scala中提供了lazy值的特性,如果将一个变量声明为lazy,则只有在第一次使用该变量时,变量对应的表达式才会发生计算。这种特性对于特别耗时的计算操作特别有用,比如打开文件进行IO,进行网络IO。
import scala.io.Source._lazy val lines = fromFile("D://text.txt").mkString

  • 异常
  • 在scala中,异常处理和捕获机制与java非常相似。

示例:

try {    throw new IllegalArgumentException("illgal argument!!!")} catch{  case _:IllegalArgumentException => print("sorry,error!")} finally {  print("\nrelease io resourses!!!")}

try {    throw new IllegalArgumentException("illgal argument!!!")} catch{  case e1:IOException => println("io exception")  case e2:IllegalArgumentException => print("sorry,error!")} finally {  print("\nrelease io resourses!!!")}


一、数组操作值Array、ArrayBuffer以及遍历数组

  • scala中,Array代表的含义与Java相似,也就是长度不可变的数组。此外,由于scala与java双方可以互相调用,因此scala数组的底层实际上就是java的数组。
  • 数组初始化后,长度就固定下来了,而且元素全部根据其类型初始化
val a = new Array[Int](10)val a = new Array[String](10)
  • 也可以直接使用Array()创建数组,元素类型自动推断,也可以直接通过index进行修改元素
val a = Array("hello","world")a(0) = "hi"

数组.length可以返回数组长度

  • 在scala中,如果需要类似java中ArrayList这种长度可变的集合类,则可以使用ArrayBuffer。
  • 如果不想每次使用全限定名,可以先导入ArrayBuffer类
import scala.collection.mutable.ArrayBuffer
  • 使用ArrayBuffer()的方式可以创建一个空的ArrayBuffer

 

val b = ArrayBuffer[Int]()
  • 使用+=操作符,可以添加一个元素,或者多个元素。重点,spark源码里大量使用了这种集合操作语法
b += 1b += (2,3,4,5)

  • 使用 ++= 操作符,可以添加其他集合中的所有元素
b ++= Array(6,7,8,9,10)

  • 使用trimEnd()函数,可以从尾部截断指定个数的元素
b.trimEnd(5)

  • 使用insert()函数可以在指定位置插入元素,但是这种操作效率很低,因为需要移动指定位置后的所有元素
b.insert(5,6)b.insert(6,7,8,9,10)

 

  • 使用remove()函数可以移除指定位置的元素
b.remove(1)b.remove(1,3)

 

  • Array与ArrayBuffer可以互相进行转换
b.toArraya.toBuffer

 

  • 遍历Array和ArrayBuffer
  • 使用for循环和until遍历Array/ArrayBuffer
for (i <- 0 until b.length) println(b(i))

  • 跳跃遍历Array/ArrayBuffer
for (i <- 0 until (b.length,2)) println(b(i))

  • 从尾部遍历Array/ArrayBuffer
for (i <- (0 until b.length).reverse) println(b(i))

  • 使用“增强for循环” 遍历Array/ArrayBuffer
for (e <- b) println(e)

数组元素求和

val a = Array(1,2,3,4,5)val sum = a.sum

 获取数组最大值

val max = a.max

对数组进行排序

scala.util.Sorting.quickSort(a)

获取数组中的所有元素内容

a.mkStringa.mkString(",")a.mkString("(",",",")")

ArrayBuffer的toString与Array不太一样,主要区别在于“toString”

import scala.collection.mutable.ArrayBufferval b = ArrayBuffer[Int]()b += (1,2,3,4,5)b.toStringb.mkString

二、数组操作之数组转换

  • 使用yied和函数式编程转换数组
  • 对Array进行转换,获取的还是Array
val a = Array(1,2,3,4,5)val a2 = for(ele <- a) yield ele * ele
  • 对ArrayBuffer进行转换,获取的还是ArrayBuffer
val b = ArrayBuffer[Int]()b += (1,2,3,4,5)val b2 = for(ele <- b) yield ele * ele
  • 可以利用if守卫,转换仅需转换的元素
val a3 = for (ele <- a if ele % 2 == 0) yield ele * ele
  • 使用函数式编程转换数组(常用的是第一种方式)
a.filter(_ % 2 == 0).map(2 * _)a.filter{_ % 2 == 0} map{2 * _}
  • 算法案例:移除第一个负数后面的所有负数
val a = ArrayBuffer[Int]()a += (1,2,3,4,5,-1,-3,-5,-9)var foundFirstNegative = falsevar arrayLength = a.lengthvar index = 0while(index < arrayLength) {    if (a(index) >= 0) {        index += 1    } else {        if (!foundFirstNegative){foundFirstNegative = true;index += 1}      else{a.remove(index);arrayLength -= 1}    }}
  • 优化后的算法
val a = ArrayBuffer[Int]()a += (1,2,3,4,5,-1,-3,-5,-9)var foundFirstNegative = falseval keepIndexes = for (i <- 0 until a.length if !foundFirstNegative || a(i) >= 0) yield{    if (a(i) < 0) foundFirstNegative = true    i}for (i <- 0 until keepIndexes.length){a(i) = a(keepIndexes(i))}a.trimEnd(a.length - keepIndexes.length)

Map与Tuple

  • 创建不可变的Map
val age = Map("leo" -> 23,"jack" -> 34)val age = Map(("leo",12),("jack",33))
  • 创建可变的Map
val ages = scala.collection.mutable.Map("leo" -> 12,"mary" -> 25)ages("leo") = 31
  • 创建空的HashMap
val ages = new.scala.collection.mutable.HashMap[String,Int]
  • 访问Map的元素
val leoage = ages("leo")  (如果key不存在,则报错)

使用contains函数检查是否存在

val leoage = if (ages.contains("leo")) ages("leo") else 0

getOrElse函数

val leoage = ages.getOrElse("leo",0)
  • 修改可变Map的元素

更新Map的元素

ages("leo") = 31

增加多个元素

ages += ("mike" -> 34,"lucy" -> 35)

移除元素

ages -= "mike"
  • 更新不可变Map的元素
val ages2 = age + ("tom" -> 23,"bob" -> 26) (这里的age是不可变Map)
  • 移除不可变Map的元素
val ages3 = ages2 - "tom"
  • 遍历Map

遍历Map的entrySet

for ((key,value) <- ages) println(key + " " + value)

遍历Map的key

for (key <- ages.keySet) println(key)

遍历Map的value

for (value <- ages.values) println(value)

生成新Map 反转key和value

for ((key,value) <- ages) yield (value,key)
  • SortedMap可以自动对Map的key的排序
val ages = scala.collection.immutable.SortedMap("leo" -> 30,"bob" -> 23)
  • LinkedHashMap可以记住插入entry的顺序

Map的元素类型——Tuple 



面向对象编程之类

  • 定义类,包含field方法
class HelloWorld{  private var name = "leo"  def sayHello(){print("hello," + name)  def getname = name}

 

  • getter与setter

  • 自定义getter和setter 
  1. 如果只是希望拥有简单的getter和setter方法,那么就按照scala提供的语法规则,根据需求为field选择合适的修饰符就好:var、val、private、private[this]
  2. 但是如果希望能够自己对getter和setter进行控制,则可以自定义getter和setter方法
  3. 自定义setter方法的时候一定注意scala的语法规则,签名、=、参数之间不能有空格 
class Student{  private var myName = "leo"  def name = "your name is " + myName  def name_=(newValue:String){   print("you cannot edit your name!") }}

 

  • 仅暴露field的getter方法

class Student{  private var myName = "leo"  def updateName(newName:String){   if (newName == "leo1") myName = newName   else println("not accept this new name," + newName)   }  def name = myName}

 

  • private[this]的使用 

class Student{  private var myAge = 0  def age_=(newValue:Int){   if (newValue > 0) myAge = newValue   else print("illegal age!")  }  def age = myAge  def older(s:Student) = {   myAge > s.myAge  }}

class Student{  private[this] var myAge = 0  def age_=(newValue:Int){   if(newValue > 0) myAge = newValue   else println("illegal age!")  }  def age = myAge  def older(s:Student) = {   myAge > s.myAge  }}

 

  • java风格的getter和setter方法 

import scala.beans.BeanPropertyclass Student{  @BeanProperty var name:String = _}或者class Student(@BeanProperty var name:String)

 

  • 辅助 constructor

 

class Student{    private var name = ""    private var age = 0    def this(name:String){        this()        this.name = name    }    def this(name:String,age:Int){        this(name)        this.age = age    }}

  • 主constructor

 

class Student(val name:String,val age:Int){    println("your name is "+ name +",your age is "+ age)}

 

 

class Student(val name:String = "leo ",val age:Int = 30){    println("your name is "+ name +",your age is "+ age)}

 

  • 内部类

 

import scala.collection.mutable.ArrayBufferclass Class{    class Student(val name:String)    val students = new ArrayBuffer[Student]()    def getStudent(name:String) = {        new Student(name)    }}

 

转载地址:http://bvnhb.baihongyu.com/

你可能感兴趣的文章
开源意义_有用的陌生人和开源的意义
查看>>
最佳 开源 人脸识别算法_2014年最佳开源教程
查看>>
foss测试_2014年FOSS十大法律发展
查看>>
本周最热门的5篇文章:Raspberry Pi A +,Ansible和Jen的Linux历程
查看>>
owncloud_一周前五篇文章:Linux理念,ownCloud集成等
查看>>
最佳 开源 人脸识别算法_本周最佳5篇文章:今年最佳开源,以及更多
查看>>
firefox 开源_一周最热门的5篇文章:移动版Firefox OS和年度开源奇迹
查看>>
18年开源前端框架排名_2014年排名前20位的开源故事
查看>>
十大开源项目_2014年十大开源访谈
查看>>
展望2019年_感谢您创纪录的一年(并展望2015年)
查看>>
go开源项目整理-新手篇_一周的前5篇文章:您正在从事什么开源项目?
查看>>
您不懂JavaScript,但您应该
查看>>
医疗项目 开源_免费和开源医疗保健成功的背后是什么?
查看>>
开源教学系统_通过开源进行教学和口语学习
查看>>
命令行python路径命令_探索命令行英雄中Python的过去,现在和未来
查看>>
Codethink开源是入职流程的一部分
查看>>
kubernetes 集群_使用k9s加速Kubernetes集群的管理
查看>>
fsf不推荐debian_FSF揭示了他们用于聊天,视频等的工具
查看>>
kubernetes 应用_Kubernetes如何保存我的桌面应用程序
查看>>
kubectl命令_系统管理员需要了解的9个kubectl命令
查看>>