您的位置:首页 > 其它

Scala 基础总结

2016-11-23 14:10 162 查看


数据类型


String

String 本不算什么基础类型,Scala String 类型有些特点简单介绍几点


字符串插值(String Interpolation)

字符串插值一句话解释:能在字符串定义中直接嵌入变量的引用,举个例子:
val name = "wuzheng"

println(s"hello $name ")  // hello wuzheng


第二句中的
$name
 是引用了前面定义的变量
name
在字符串定义前加
s
¥{}
当然也可以嵌入表达式。
println(s"1 + 1 = ${1 + 1}")   // 1 + 1 = 2


本质上
s
是一个function ,自然可以定义其他的函数,比如Scala 自己就提供了
f
用于格式化输出。
val name = "wuzheng"

val height = 1.9d

println(f"$name%s is $height%2.2f meters tall")  // wuzheng is 1.90 meters tall


上面这个例子改自官方文档(当然我没那么高)。这种格式化Python 里面是有相似的东西的。Python 里也有相似的东西比如在字符串开头添加
r
来屏蔽字符串转意比如:
print(r"Hello \n wuzheng")


上面这句就不会输出换行符,而是直接输出
\n
 Scala 也有,不过不是
r
 而是
raw

println(raw"hello \n wuzheng")


当然可以自定义插入的符号,因为本质上这些都是函数,字符串插值应该是Scala2.10之后才有的。字符串本身还有正则,等一些操作,感觉和其他语言差异不大,不再细述。


数值

Scala 有如下几种内建数值类型

Char 16位无符号Unicode

Byte 8位有符号整数

Short 16位有符号整数

Int 32位有符号整数

Long 64位有符号整数

Float

Double


自增自减

Scala 和 和Python 一样没有
++
 和
--
运算。


浮点数的比较

两个本来相等的浮点数可能时间上不相等比如
scala> val b = 0.1 + 0.2

b: Double = 0.30000000000000004


而且
scala> b == 0.3

res0: Boolean = false


可以自定义近似相等来解决比如
def simEqual(x: Double, y: Double, precision: Double) = {

if ((x - y).abs < precision) true else false

}



产生整数序列

Python 有
range
函数,Scala 提供了,
to
until
.
until
得到的是包含下界,不包含上界的半包半闭区间,
to
则包含下界和上界。


控制结构

Scala 的控制结构很多地方是我很难适应的,从C, C++, Java ,Python 一路走来控制结构几乎没有多大的变化,但是Scala 做出了很大的改变。


去掉的关键字

Scala 没有了
break
continue
,甚至
return
 关键字,
return
没了还好,如故是函数就是做后一句写上要返回的变量。但是如果你习惯了在控制结构中使用
return
估计就麻烦了。还有,很多时候,特别是C,C++,Java
的时候没有
break
,
continue
这两个东西那真是”宝宝办不到“啊。

至于这其中的原因,和好处估计得慢慢体会了。

还好Scala 提供了类似的东西来替代,虽然麻烦了但是非用不可的时候还是需要的。

object ControllExample {

def main(args: Array[String]) {

breakable {

for (i <- 1 to 10) {

println(i)

if (i > 5) {

break

}

}

}

}

}


Continue 也可类似处理。


for 循环的特殊之处


卫语句


意思是for 中嵌入if 语句,比如输出1到10偶数
for (i <- 1 to 10 if i % 2 == 0) {

println(i)

}



for/yield


for
 和 
yield
结合感觉和Python的迭代器类似,会产生一个可迭代
的对象。
val a = Array("wu", "zheng", "Hello")

val lengths = for(e<-a) yield {

e.length()

}

lengths.foreach(println(_))



switch 和模式匹配


说老实话swith 我一般用得较少,但是Scala 的switch 我觉得不能不说,结合Scala 的模式匹配,感觉就不得不提了。
val i = 1

val x =  i match {

case 1 => "one"

case 2 => "two"

case _ => "many"

}


这感觉是不是和switch 和相似?,都推荐使用
@switch
 在不能编译成
tableswitch
lookswitch
的时候会有警告。
val i = 1

val x =  (i: @switch) match {

case 1 => "one"

case 2 => "two"

case _ => "many"

}


一个
case
可以匹配多个值
val i = 4

val x =  (i: @switch) match {

case 1 | 2 => "one"

case 4 | 3 => "two"

case _ => "many"

}

println(x)


case 语句中可以使用,常量模式,变量模式,构造函数模式,序列模式,元组模式,或者类型模式。
def echoCase(x: Any): String = x match {

case 0 => "zero"

case true => "true"

case "hello " => "hello wuzheng"

case Nil => "空数组"


case List(0, _, _) => "三个元素的序列,其中第一个为0"

case List(1, _*) => "第一个元素为1序列"


case s: String => s"输入的值是 String : $s"

case i: Int => s"输入的是整数: $i"

case _ => "我不知道了"


}


try/catch 也是使用case 捕获异常

val s = "wu zheng"

try {

val i = s.toInt

}catch {

case e: Exception => e.printStackTrace()

}



函数

Scala 不是单纯的OOP 语言,它还是FP语言,这和Python 很类似 但又有很多强大的特性。


匿名函数

在Python 中有
lambda
关键字定义匿名函数,Scala 的更直接
scala> (x: Int) => x+1

res8: Int => Int = <function1>


scala> res8(3)

res9: Int = 4


可以把匿名函数保存为变量,或直接进行传递
var a = List(1,2,3)

val addOne = (x: Int) => x + 1

a.map(addOne)



部分应用(Partial application)柯里化(Currying)

部分应用,和Python的函数默认参数类似,但是你可以随意改变默认参数的值,这样就能得到很多不同默认参数的函数了。
val sum = (a: Int, b: Int, c: Int) => a + b + c

val f = sum(1, 2, _: Int)

println(f(3))


把函数定义方式变一下,可以实现Currying ,柯里化的意思shi把原来接收两个参数的函数变成接收一个参数的函数
def multiply(m: Int)(n: Int): Int = m * n

val multiT = multiply(2) _

println(multiT(3))



闭包

这部分感觉还没理解太透,看到一个例子
var factor = 3

val multiplier = (i:Int) => i * factor


意思是函数multiplier 可以访问变量factor, 有段话是这样解释的

闭包是一个函数,返回值依赖于声明在函数外部的一个或多个变量。

闭包通常来讲可以简单的认为是可以访问一个函数里面局部变量的另外一个函数。


OOP

类的定义
class Calculator(brand: String) {

/**

* 构造函数部分

*/

val color: String = if (brand == "TI") {

"blue"

} else if (brand == "HP") {

"black"

} else {

"white"

}


//  实例方法

def add(m: Int, n: Int): Int = m + n

}


构造函数就是除了方法之外的代码,还可以定义辅助构造函数,有点像Java 的构造函数的重载。使用
this
 关键字
def this(brandSize: Int,){

this("a")// 调用之前的构造函数

}


辅助构造函数必须满足:

用this关键字为名创建

必须从调用之前定义的构造函数开始

每个构造函数要有不同的签名

一个构造函数通过this调用另一个构造函数


Traits(特质)

Traits(特质) 类似Java 的接口(interfaces),不同的是,允许用户对不放方法在Traits中实现。
trait Similarity {

def isSimilar(x: Any): Boolean

def isNotSimilar(x: Any): Boolean = !isSimilar(x)

}



抽象类

和Traits 类似,可以被子类继承,但是不同的是,可以有自己的主构造函数,Traits 是没有构造函数的。在和Java 交互的时候也需要定义抽象类。所以需要有主构造函数的时候就使用抽象类。但是通常是使用Traits因为后者更加灵活。


继承

一个类只能继承一个抽象类,但是一个可以继承多个特质。

如果一个类继承了特质使用
extends


如果继承了多个特质第一个使用
extends
其余的使用
with


如果一个类继承了一个类和一个特质,继承类使用
extends
特质使用
with


abstract class Animal {


}

trait WaggingTail{


}

class Dog extends Animal with WaggingTail {


}



Mixin(混入)

官方文档有详细的例子和说明。意思就是可以通过
extends
或者
with
获得一个或多个特质的特性


数据结构


基础数据结构


List


感觉和Python的list 挺像,不同的是取元素的时候是使用
()
.List中也是可以放入不同类型的。
val numbers = List(1, 2, 3, 4)

numbers(1)                                  // 2



Set


不重复集合

val s = set(1,2,3,4,2)

元组

val hostPort = ("localhost", 80)

hostPort._1    //第一个元素

hostPort._2   // 第二个元素



Map

Map(1 -> 2)

Map("foo" -> "bar")



函数组合子(Functional Combinators)

不太好说这个定义Stackoverflow上有个说明 可以去看下,搞不清楚就直接看例子好了。其实我理解就是一些能把函数应用在数据结构上的方法,比如
map
,
filter
 
flatmap
等等。

map

scala> val numbers = List(1, 2, 3, 4)

numbers: List[Int] = List(1, 2, 3, 4)


scala> numbers.map((i: Int) => i * 2)

res14: List[Int] = List(2, 4, 6, 8)



foreach


和map 类似有一个隐式循环,但是没有返回值
numbers.foreach((i: Int) => i * 2) //不会产生一个新的List



filter


去掉那些不满足条件的元素,得到一个新的结构
numbers.filter((i: Int) => i % 2 == 0)



zip


Python 也有的哟,很好用。
scala> List(1, 2, 3).zip(List("a", "b", "c"))

res0: List[(Int, String)] = List((1,a), (2,b), (3,c))



partition


可以分割列表
scala> val numbers = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

scala> numbers.partition(_ % 2 == 0)

res0: (List[Int], List[Int]) = (List(2, 4, 6, 8, 10),List(1, 3, 5, 7, 9))



find


和filter 操作相反,返回满足条件的元素
numbers.find((i: Int) => i > 3)


还有好多看这里


隐式转换

这是我最后想说的东西。如果要给一个类添加一些自定义方法,在Java中需要继承,然后定义一个方法,在Scala有隐式转化来实现。

举个简单的例子,把字符串的每个字符值加1得到一个新的字符串
implicit class StringImprovements(s:String){

def increment = s.map(c => (c+1).toChar)

}

println("KNUD".increment)   //输出:LOVE


理想很丰满,现实总是很骨干,不会Java 来用Scala总是感觉在耍流氓
参考:
Scala DOCUMENTATION
Scala School
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: