spark入门之scala学习笔记

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

一、定义函数

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 " + name

def 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 += 1

b += (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.toArray

a.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.mkString

a.mkString(",")

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

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

import scala.collection.mutable.ArrayBuffer

val b = ArrayBuffer[Int]()

b += (1,2,3,4,5)

b.toString

b.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 = false

var arrayLength = a.length

var index = 0

while(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 = false

val 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.BeanProperty

class 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.ArrayBuffer

class Class{
    class Student(val name:String)
    val students = new ArrayBuffer[Student]()
    def getStudent(name:String) = {
        new Student(name)
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值