scala学习笔记整理

会有一股神秘感。 提交于 2019-11-26 17:31:41

scala基础知识

概述
静态类型语言(scala/java)、面向对象编程,面向函数式编程、
优点:scala与java可以无缝链接、速度快、简洁优雅、快速融入大数据生态圈(spark)、scala工程师…
静态类型语言:变量的数据类型在程序编译阶段确定。
动态类型语言:变量的数据类型在程序运行阶段确定。
基于JVM(a.scala—>a.class(java)---->JVM)

基本数据类型

Byte、Short、Int、Long、Float、Double、String、Char、Boolean(首字母大写、与java类似)

Byte 8位有符号补码整数。数值区间为 -128 到 127
Short 16位有符号补码整数。数值区间为 -32768 到 32767
Int 32位有符号补码整数。数值区间为 -2147483648 到 2147483647
Float 32 位, IEEE 754标准的单精度浮点数,浮点数后带F/f的就是Float
Char 16位, 无符号
Double 64位, 双精度浮点数
String 由Char数组组成
Boolean true 或者 false

Unit的类型
相当于Java/c/c++中的void,只有唯一值,用空的括号表示()

操作符
算数运算符(+.-.*./)、
关系运算符(>.<.=.!=.>=.<=)、
逻辑运算符(&&.||.!)、
位运算符(&,|,^,~,<<,>>,>>>)

scala关键字

abstract    case        catch       class       def
do          else        extends     false       final
finally     for         forSome     if          implicit
import      lazy        macro       match       new
null        object      override    package     private
protected   return      sealed      super       this
throw       trait       try         true        type
val         var         while       with        yield
_    :    =    =>    <-    <:    <%     >:    #    @

变量

val 变量名:数据类型 = 初始值
var 变量名:数据类型 = 初始值
1)声明变量时,类型可以省略;
2)类型确定后,不能修改;
3)var修饰的变量可以改变,val修饰的变量不可改变;
lazy关键字
lazy可以延迟初始化字段,加上lazy的字段会在第一次访问的时候初始化,而不是类初始化的时候,lazy非常适合于初始化非常耗时的场景。

表达式 if-else语句、 for、while、do…while、foreach迭代

if…else语句

 if (表达式){
       语句块1
 }
 else{
       语句块2
}
  def myFactor(x:Int):Int = {
          |      if(x<=1)
          |          1   // 注意:Scala的函数中,函数的最后一句话就是函数的返回值
          |      else
          |          myFactor(x-1)*x
          | }

for循环

**for(变量 <- 表达式) {语句块}**

```
for ( i <-  Array(1,2,3))  println( i )
```

通过使用被称为发生器(generator)的语法“files<-filesHere”,遍历了list里的元素,每一次枚举,名为s的新的val就被元素值初始化,函数体println(i)也将被执行一次
在写for循环的时候,可以在for表达式的括号里添加不止一个过滤器(if子句必须用分号分隔),同样的,生成器也是可以加入超过一个的,这样就等同于其他语言的for循环嵌套。

#过滤器
for (i<- 1 to 5)
      if(i%2==0)  println(i)
##生成器
for (i<- 1 to 5 ; j<- 1 to 3)  println(i*j)

之前的例子都是对枚举值进行操作,然后就释放。在for表达式之后加上关键字yield(for推导式),就可以创建一个值(数组集合Vector)去记住每一次的迭代。
while循环

while(表达式){
       循环体
}
或
do{
      循环体
  }while(表达式)

while循环分两种:while和do-while
之所以把while称为循环,而不是表达式,是因为它们不能产生有意义的结果,结果的类型是Unit
foreach迭代遍历
这里的例子使用集合的foreach方法进行迭代,输出list里的数据.

  var list = List("JAVA","C++","Python")
    
    list.foreach(element => println(element))
    
    list.foreach((element:String) => println(element))
    
    list.foreach {println}

函数与方法

Scala 中使用 val 语句可以定义函数,def 语句定义方法,但本质上两者没什么区别。Scala 方法是类的一部分,而函数是一个对象可以赋值给一个变量。换句话来说在类中定义的函数即是方法。

 ##函数实例
 def 函数名(参数名1: 参数类型1, 参数名2: 参数类型2) : 返回类型 = {函数体}
 
   call by value:对函数实参进行求值,并且只求一次
   call by name:函数实参在函数内部调用的时候,才会求值,每次都会求值
                 举例:Call by value 使用冒号
                               def func1(x:Int,y:Int):Int = x + x
                      
                       Call by name 使用 : =>
                               def func2(x: => Int,y: => Int):Int = x + x
                      
                      调用:    
                              func1(3+4,8)
                      执行过程 1:fun1(7,8)
                                      2:7+7
                                      3:14
                      
                              func2(3+4,8)
                      执行过程 1:(3+4)+(3+4)
                                      2:7 +(3+4)
                                      3:7 + 7
                                      4:14
                               

##方法实例:递归实现斐波那契
scala> def Fibonacci(n:Int):Int={
     | if (n<=2 && n>0) 1
     | else Fibonacci(n-1)+Fibonacci(n-2)
     | }
Fibonacci: (n: Int)Int
scala> for(i<-1 to 10)
     | print(Fibonacci(i)+" ")
1 1 2 3 5 8 13 21 34 55

Scala 中的方法跟 Java 的类似,方法是组成类的一部分。
Scala 中的函数则是一个完整的对象,Scala 中的函数其实就是继承了 Trait 的类的对象。
Scala的Lazy特性(懒执行特性)
当一个变量被申明是lazy,他的初始化会被推迟,直到第一次使用他的时候,才会被初始化

Scala对象

单例对象
Scala本身没有提供定义静态字和静态方法,我们可以使用Object来达到这个目的。通过Object字段来定义单例对象
class 和 object 的区别:
object是class的伴随对象。 scala中没有static关键字,所以java中static类型的变量、方法都要放在scala的object里非static的放在class里。
伴生对象
在Java中我们可以在类中定义实例方法和静态方法,但是在Scala中类中的静态方法和静态常量是通过伴生对象来完成的。
apply方法
Scala在对象中提供了apply方法,当我们使用对象名加参数直接调用时,就是调用对象中的apply方法。
特质trait
trait - scala中的类interface物,但是可以拥有方法体,并且可以在类实例化时混入,而不需为了包装某个类而产生子类
高阶函数
函数可以传递给另一个函数使用,而接受函数类型参数的函数称为高阶函数。
偏应用函数
如果我们想定义一个函数,让换个函数只处理定义域内的子集,对于这个定义域的参数抛出异常,这样的函数称为偏函数(这个函数只处理传递过来的部分函数)。
闭包
当我们在定义的匿名函数中使用外部变量时,该变量可能会不断的变化,它处于一种开发状态,而当我们执行函数时,这个自由变量就被确定下来了,这时候我们可以认为运行时该变量处于封闭状态,这种存在由开放到封闭的过程,称为闭包。当然引用的外部变量也可是函数,比如高阶函数。这种类型的函数,称为闭包函数。闭包由代码和代码用到的非局部变量构成。

数组

定长数组:Array

 val a = new Array[Int] (10)
 val b = new Array[String](5)

对数组直接进行初始化

 val c = Array("java","php","scala")
 val a = new Array[Int] (1,2,4,9,5) 

变长数组:ArrayBuffer

 import scala.collection.mutable._
 val d = ArrayBuffer[Int]()

定长数组与变长数组的转换

arr1.toBuffer
arr2.toArray

多维数组

//定义
val arr3 = Array.ofDim[Double](3,4)
//赋值
arr3(1)(1) = 100

映射

Map是一种可迭代的键值对(key/value)结构,所有的值都可以通过Key来获取,Map 中的Key都是唯一的。
Map 也叫哈希表(Hash tables)
Scala可以提供了两种类型的映射,一种是可变的Map,一种是不可变的Map。
构造不可变映射 immutable

val map1 = Map("java" -> 10, "scala" -> 20, "spark" -> 30)

构造可变映射 mutable

val map2 = scala.collection.mutable.Map("hadoop" -> 10, "java" -> 20, "php" -> 30)

取值

val value1 = map1("java")//建议使用get方法得到map中的元素
println(value1)

遍历

for (v <- map1.keys) println(v)
for (v <- map1.values) println(v)
for(v <- map1) prinln(v)

元组

元组可以包含不同类型的元素,映射中的键值对偶就是元组的最简单形式。
Tuple不能直接用foreach来遍历,所以要使用迭代器再foreach进行遍历
Tuple还可以使用tostring方法来将元组转换成字符串
元组的创建

val tuple1 = (1, 2, 3, "java")

元组数据的访问 元组元素的访问有下划线 访问下标从1开始,而不是0

val value1 = tuple1._4
println(value1)

元组的遍历
tuple1.productIterator.foreach(i => println(i))
tuple1.productIterator.foreach(print(_))

集 Set

集是不重复元素的结合。
集不保留顺序,默认是以哈希集实现。
SortedSet(排序数据集)

默认不可变集合,使用可变集合,需要引用 scala.collection.mutable.Set 包。
不可变集合的创建

val set = Set(1, 2, 3)
println(set)

可变集合的创建

import scala.collection.mutable.Set
val mutableSet = Set(1, 2, 3)

可变集合的元素添加

    mutableSet.add(4)
    mutableSet += 6
// 注意该方法返回一个新的Set集合,而非在原有的基础上进行添加
    mutableSet.+(5)

可变集合的元素删除

mutableSet -= 1
mutableSet.remove(2)
println(mutableSet)

遍历

for(x <- mutableSet) {
  println(x)
}

1 def +(elem: A): Set[A] 为集合添加新元素,并创建一个新的集合,除非元素已存在
2 def -(elem: A): Set[A] 移除集合中的元素,并创建一个新的集合
3 def contains(elem: A): Boolean 如果元素在集合中存在,返回 true,否则返回 false。
4 def &(that: Set[A]): Set[A] 返回两个集合的交集
5 def &~(that: Set[A]): Set[A] 返回两个集合的差集
6 def ++(elems: A): Set[A] 合并两个集合
7 def drop(n: Int): Set[A]] 返回丢弃前n个元素新集合
8 def dropRight(n: Int): Set[A] 返回丢弃最后n个元素新集合
9 def dropWhile(p: (A) => Boolean): Set[A] 从左向右丢弃元素,直到条件p不成立
10 def max: A 查找最大元素
11 def min: A 查找最小元素
12 def take(n: Int): Set[A] 返回前 n 个元素

集合元素与函数的映射

map:将集合中的每一个元素映射到某一个函数

val names = List("nike", "adidas", "lining")
println(names.map(_.toUpperCase))

flatmap:flat即压扁,压平,扁平化,效果就是将集合中的每个元素的子元素映射到某个函数并返回新的集合

val names = List("kobe", "wade", "curry")
println(names.flatMap(_.toUpperCase()))

化简、折叠、扫描

折叠,化简:将二元函数引用于集合中的函数

val list = List(1, 2, 3, 4, 5)
val i1 = list.reduceLeft(_ - _)
val i2 = list.reduceRight(_ - _)
println(i1)
println(i2)

.reduceLefft(_ - _)这个函数的执行逻辑如图所示:

.reduceRight(_ - _)反之同理
折叠,化简:fold
fold函数将上一步返回的值作为函数的第一个参数继续传递参与运算,直到list中的所有元素被遍历。可以把reduceLeft看做简化版的foldLeft。相关函数:fold,foldLeft,foldRight,可以参考reduce的相关方法理解。

val list2 = List(1, 9, 2, 8)
val i4 = list2.fold(5)((sum, y) => sum + y)
println(i4)

foldRight

val list3 = List(1, 9, 2, 8)
val i5 = list3.foldRight(100)(_ - _)
println(i5)

foldLeft和foldRight有一种缩写方法对应分别是/:和:\
例如:
foldLeft

val list4 = List(1, 9, 2, 8)
val i6 = (0 /: list4)(_ - _)
println(i6)

扫描
即对某个集合的所有元素做fold操作,但是会把产生的所有中间结果放置于一个集合中保存。

val i8 = (1 to 10).scanLeft(0)(_ + _)
println(i8)

拉链

val list1 = List("15837312345", "13737312345", "13811332299")
val list2 = List(17, 87)
 val  z1= list1.zip(list2)   //形成(15837312345,17)(13737312345,87)其他列表中的多余的元素舍弃
println(z1)

迭代器

通过iterator方法从集合获得一个迭代器,通过while循环和for表达式对集合进行遍历。

val iterator = List(1, 2, 3, 4, 5).iterator
while (iterator.hasNext) {
  println(iterator.next())
}
或:
for(enum <- iterator) {
  println(enum)
}

scala 转义字符

\b,\u0008,退格(BS)

\t,\u0009,水平制表(HT)

\n,\u000a,换行(LF)

\f,\u000c,换页(FF)

\r,\u000d,回车(CR)

",\u0022,双引号

',\u0027,单引号

\,\u005c,反斜线

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!