剑客
关注科技互联网

Scala 基础总结

Scala 基础总结

[TOC]

Scala 新手打算聊聊Scala 的一些特性。详述这里的所有内容合起来都够写一本书了,定有不周到的地方,看不下去的可以去About 页面找到我的邮箱邮件给我,纯属个人学习所用,如果不小心对你有帮助,纯属偶然。

数据类型

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

分享到:更多 ()

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址