scala成长之路(1)基本语法和数据类型

scala作为JVM上的Lisp,是一种geek类型的编程语言,也一直是我等java程序员眼中的梦寐以求的一门技能,遂下定决心花一段时间好好学习scala。第一天学习,主要介绍与java在编程上的主要区别。

首先,scala默认导入了java.lang包下的所有类,因此在scala中可以直接使用所有该包下的所有类,例如System、String

1. scala与java不同的一点是:scala是完全面向对象的,它没有基本数据类型,所有的变量、字面量或常量都是对象,所以你可以看到这种调用方式

scala> 1.toString()
res3: String = 1

因此,scala的数据类型基本都与java的基本数据类型包装类相对应:

数据类型描述
Byte 8位有符号补码整数。数值区间为 -128 到 127
Short 16位有符号补码整数。数值区间为 -32768 到 32767
Int 32位有符号补码整数。数值区间为 -2147483648 到 2147483647
Long 64位有符号补码整数。数值区间为 -9223372036854775808 到 9223372036854775807
Float 32 位, IEEE 754标准的单精度浮点数
Double 32 位 IEEE 754标准的单精度浮点数
Char 16位无符号Unicode字符, 区间值为 U+0000 到 U+FFFF
String 字符序列
Boolean true或false
Unit 表示无值,和其他语言中void等同。用作不返回任何结果的方法的结果类型。Unit只有一个实例值,写成()。
Null null 或空引用
Nothing Nothing类型在Scala的类层级的最低端;它是任何其他类型的子类型。
Any Any是所有其他类的超类
AnyRef AnyRef类是Scala里所有引用类(reference class)的基类

注意其中的Unit类型,它和null不一样,null只能用于引用类型,不能用于数据类型:

scala> var a : Int = null
<console>:11: error: an expression of type Null is ineligible for implicit conversion
var a : Int = null

而Unit类型更多的是用于返回值表示没有返回值,也即返回值为空。scala中每个表达式都有返回值,但与c语言不同的是,scala中赋值表达式的返回值为空;而且scala中每个代码块都有返回值,即为代码块最后一行的返回值:

scala> var a = {println("hello world");var b = "aaa";b += "ccc"}
hello world
a: Unit = ()

2. 与其他函数式编程语言一样,函数在scala里也被视为“一等公民”,即函数可赋值,可作为参数进行传递,可作为返回值:

 

3. scala的for循环与java有所不同,它类似于python,只能用于遍历某个集合(但python还是可以通过enumerate来获得当前元素的位置信息,而scala则无此功能):

scala> for(i<-1 to 10)
| print(i + ",")
1,2,3,4,5,6,7,8,9,10,

 同时,for循环的嵌套可以写在用一个for中,不同的层次之间用分号;链接:

for(i <- 1 to 9;j <- 1 to 3){
printf("%d,%d\n",i,j)
}

4. Array, List, Set, Map

首先需要明确,scala中的这四种容器类与java都是完全不同的,scala中除Tuple之外,所有容器都有类型指定

(1)Array是定长可变容器,类似于java中的list的定长版本,而且Array还需指定元素类型类似于java的泛型,注意使用的是中括号[]:

scala> var a = new Array[String](3)
a: Array[String] = Array(null, null, null)

如果使用显示初始化,则不需要new,类型自动推断:

scala> var a = Array(1,"12")
a: Array[Any] = Array(1, 12)

需要指出的是,在scala中,直接调用任何类的(),都等价于其apply方法,所以前边的程序也可以写作:var b = Array.apply(1,2,3)。而Array的索引下标则从0开始,可以修改任意元素的值:a(1) = 32,其等价于a.update(1,32)。此外,Array虽然是定长的,但是可以拼接其他可迭代容器,使用++生成一个新的Array:

scala> a ++ b
res10: Array[Int] = Array(1, 2, 3, 4)

(2)List是定长的不可修改容器,因此只能使用显式初始化:var a = List(1,3,4)。同时,List也提供类似的添加和拼接功能,分别利用:::和::进行List间的拼接以及添加元素:

var a = List(1,2,3)
var b = List(4,5,6)
a:::b
7::a

res17: List[Int] = List(7, 1, 2, 3)

需要注意的是,:::以及::都是右结合操作符,即将7添加到a应该是7::a而不是a::7,是右边的元素为操作方,左边为参数,同理,有一种创建List的方法:

scala> 1::2::3::Nil
res22: List[Int] = List(1, 2, 3)

其中Nil为默认导入的单例,其为一个空List

list的元素是不可变的,试图向其中的元素赋值会报错

scala> a(1) = 3
<console>:13: error: value update is not a member of List[Any] (从这里也可以看出等号左边的括号()解释器实际将其解释为update方法)
a(1) = 3

注意,List和Array都有个特点:一旦确定容器的类型,那么从容其中取出的元素也会默认为该类型,例如上边的 a由于在创建时指定了两种类型,则将List定位他们的公共父类:Any

scala> a(1)
res25: Any = aaa

(3)Tuple比较简单,它也许不能称为一种容器,它也是元素不可变的,但是它没有指定类型,即它可以同时容纳多种类型,取出时仍然是自身的类型:

scala> var b = (1,true,"a",2.2)
b: (Int, Boolean, String, Double) = (1,true,a,2.2)

Tuple有长度限制,最长为22,取出时也很特殊:b._1, b._2,下标从1开始

(4)Set和Map

Set和Map都有两种不同的实现:Mutable (可变)和 Immutable (不可变)

set的两种实现类型

Map的两种实现类型

需要指出的是,默认直接使用的Set和Map都是不可变的,即默认导入的是scala.collection.immutable.Map和scala.collection.mutable.Set。

Set就是一个集合,主要用于迭代,要求其中的元素不能有重复。

Map 的基本用法如下( Map 类似于其它语言中的关联数组如 PHP )

val romanNumeral = Map ( 1 -> "I" , 2 -> "II",
  3 -> "III", 4 -> "IV", 5 -> "V")
println (romanNumeral(4))

 

posted @ 2018-08-27 22:37  王亚楼  阅读(261)  评论(0编辑  收藏  举报