前言
本篇主要讲Scala的基本数据类型,更多教程请参考: Scala教程
基本数据类型
Scala一共提供了9中数据类型,Scala的基本数据类型与java中的基本数据类型是一一对应的,这是Scala的数据类型全是类,并且头字母大写
整数类型变量定义:
//16进制
scala> val x = 0x29
x:Int = 41
//10进制
scala> val x = 41
x:Int = 41
//8进制
scala>051
res0:Int = 41
浮点型变量定义:
//Double类型定义,直接输入浮点数,编译器会将其自动推断为Double类型
scala> val doubleNumber = 3.1415
doubleNumber:Double = 3.1415
//要定义Float类型浮点数,需要浮点数后面加F或者f
scala> val floatNumber = 3.1415f
floatNumber:Float = 3.1415
//浮点型变量还可以用指数表示
scala>val floatNumber = 0.1314e1
floatNumber:Double = 1.314
字符变量定义:
//字符定义,用''将字符包裹
scala>var charLiteral='A'
charLiteral:Char='A'
常用特殊字符包括
\n换行符,其Unicode编码为(\u000A)
\b回退符,其Unicode编码为(\u0008)
\t tab制表符,其Unicode编码为(\u0009)
\" 双引号,其Unicode编码为(\u0022)
\' 单引号,其Unicode编码为(\u0027)
\反斜杠,其Unicode编码为(\u005C)
字符串变量定义:
//字符串变量用""包裹
scala> val helloWorld = "HelloWorld"
helloWorld:String = HelloWorld
//要定义"Hello World",需要加上转义符
scala> val helloWorldDoubleQuote = "\"Hello World\""
helloWorldDoubleQuote:String = "Hello World"
//如果希望能够原样输出字符串总的内容,则用三个引号"""将字符包裹
scala>println(""" hello cruel world, \n \\\ \b \\, I an""")
hello cruel world, \n \\\ \b \\, I an
布尔类型定义:
scala>var x = true
x:Boolean = true
Scala基本类型操作
因为Scala中一切皆对象,这意味着Scala中的一切操作都是对象的方法,包括基本的算术操作
算术操作:
//整数求和
scala> var sumValue = 1+2
sumValue: Int = 3
//等价于下面这句话
scala> var sumValue = (1).+(2)
sumValue:Int = 3
//操作符重载,编译器将会将其转换为(1).+(2L)执行
scala> val longSum = 1 + 2L
longSum: Long = 3
//减法
scala>1-3
res2:Int = -2
//除法
scala>1 / 3
res3:Int = 0
//取余
scala>1%3
res4:Int = 1
//乘法
scala>1*3L
res5:Long=3
//Scala中可以用+ -符号表示正负数,并且可以用来算术运算
scala>var y =1 + -3
y:Int = -2
关系运算:
//>运算符
scala> 3 > -3
res12: Boolean = true
//<运算符
scala> 3 < -3
res13: Boolean = false
//<=运算符
scala> 3 <= -3
res14: Boolean = false
//<=运算符
scala> 3 <=3
res15: Boolean = true
//<=运算符
scala> !(3<= -3)
res16: Boolean = true
逻辑运算
//逻辑与:&&
scala> val bool=true
bool: Boolean = true
scala> bool && bool
res17: Boolean = true
//逻辑或:||
scala> bool || bool
res18: Boolean = true
scala> bool || !bool
res20: Boolean = true
位运算:
// 00000001
// 00000010
// 00000000
scala> 1 & 2
res24: Int = 0
// 00000001
// 00000010
// 00000011
scala> 1 | 2
res24: Int = 3
// 00000001
// 00000011
// 00000010
scala> 1 ^ 3
res24: Int =2
//00000001
//11111110
scala> ~1
res24: Int =-2
//左移位(shift left)
//00000110
//00001100
scala> 6 << 1
res29: Int = 12
//右移位(shift left)
//00000110
//00000011
scala> 6 >> 1
res28: Int = 3
//无符号右移(shift left)
//11111111111111111111111111111111
//00000000000000000000000000000001
scala> -1 >>> 31
res32: Int = 1
对象比较:
scala> 1==1
res34: Boolean = true
scala> 1==1.0
res35: Boolean = true
scala> val x="Hello"
x: String = Hello
scala> val y="Hello"
y: String = Hello
//Scala中的对象比较不同于Java中的对象比较
//Scala基于内容比较,而java中比较的是引用,进行内容比较时须定义比较方法
scala> x==y
res36: Boolean = true
Scala程序控制结构
1、if的使用:
Scala的if/else语法结构和Java或C++一样。不过,在Scala中if/else表达式有值,这个值就是跟在if或者else之后的表达式的值。
val x = if("hello" == "hell") 1 else 0
x:Int = 0
注意点: 1、Scala的表达式都有类型,比如上面的if/else,类型为Int,因为if和else分之的类型都是Int 2、假如上面的类型不一样,比如: val x = if(x > 0) "positive" else -1 此时这两个类型就不一样了,其中一个分之是Int,而另一个分之是java.lang.String。此时这个表达式的类型是公共超类型Any。 3、如果else缺失了,比如:if(x > 0) 1 那么很可能if语句没有输出值,但是在Scala中,每个表达式都有值,此时,Scala提供了一个Unit类,写作(),上面的语句等价于: if(x > 0) 1 else () 4、赋值语句的值是Unit类型的,所以 x = y = 1 //这样是错的
2、while的使用:
def gcbLoop(x:Long, y:Long):Long = {
var a = x
var b = y
while(a != 0){
val temp = a
a = b % a
b = tmep
}
b
}
do while的使用
var line = ""
do{
line = readLine()
println("Read: "+line)
}while(line != "")
注意点:与if不用的是,while与do while不能作为表达式,也即其返回值为Unit
利用if替代while控制结构
//这样做可以减少var变量的使用,程序结构也更简单,表达能力更强
def gcb(x:Long, y:Long):Long =
if(y == 0) x else gcb(y, x % y)
var line = ""
while((line = readLine()) != "") //在Scala中不能这么用,因为Scala中的赋值语句操作返回Unit
println("Read: "+line)
for循环的使用:
scala>val filesHere = (new java.io.File(".")).listFiles
//集合操作方式
scala>for(file <- filesHere)
| println(file)
//简介调用方式
for(i <- 0 to filesHere.length - 1)
println(filesHere(i))
程序中的<-
被称为(generator),在执行过程中,集合filesHere(Array[File])的元素将依次赋给file,file类型为File,打印将调用其toString()方法将文件名打印出来。
<-生成器对其类型的集合也使用
scala>1 to 5
res10:scala.collection.immutable.Range,Inclusive = Range(1, 2, 3, 4, 5)
scala>for(i<- res10) println("Iteration: "+i)
Iteration: 1
Iteration: 2
Iteration: 3
Iteration: 4
Iteration: 5
//也可以直接写成
scala>for(i <- 1 to 5) println("Iteration: " +i)
Iteration: 1
Iteration: 2
Iteration: 3
Iteration: 4
Iteration: 5
//如果不包括5
scala>for(i <- 1 until 5) println("Iteration: "+i)
Iteration: 1
Iteration: 2
Iteration: 3
Iteration: 4
在for循环中还可以加入if进行过滤操作
val filesHere = (new java.io.File(".")).listFiles
for (file <- filesHere if file.getName.endsWith(".scala"))
println(file)
//还可以加入多个过滤条件,用;隔开
for (
file <- filesHere
if file.isFile;
if file.getName.endsWith(".scala")
) println(file)
多重循环的实现
可以使用多个变量 <- 表达式
的形式提供多个生成器,用分号将他们隔开
for(i <- 1 to 3; j <- 1 to 3) print((10 * i +j) + " ")
11 12 13 21 22 23 31 32 33
还可以使用if
for(i <- 1 to 3; j <- 1 to 3 if i!= j) print((10 * i +j) + " ")
12 13 21 23 31 32
可以使用任意多的定义,引入可以再循环中使用
for(i <- 1 to 3; from = 4 - i; j <- from to 3) print((10 * i) +j)
13 22 23 31 32 33
如果循环体以yield开始,则该循环体会构造一个集合,每次迭代生成集合中的一个值
for(i <- 1 to 10) yield i % 3
Vector(1, 2, 0, 1, 2, 0, 1, 2, 0, 1)
这类循环叫做for推导式
for推导式生成的集合与它的第一个生成器是类型兼容的。
def fileLines(file: java.io.File) =
scala.io.Source.fromFile(file).getLines.toList
def grep(pattern: String) =
for (
file <- filesHere
if file.getName.endsWith(".scala");
line <- fileLines(file)
if line.trim.matches(pattern)
) println(file +": "+ line.trim)
grep(".*gcd.*")
//前一个for相当于下列语句
def grep(pattern: String) =
for (
file <- filesHere
if file.getName.endsWith(".scala")
)
for(
line <- fileLines(file)
if line.trim.matches(pattern)
)
println(file +": "+ line.trim)
grep(".*gcd.*")
生成返回结果
//每次循环将结果保留,当整个循环执行完毕,所有保留的值将会生成一个集合并返回
scala> def scalaFiles =
| for {
| file <- filesHere
| if file.getName.endsWith(".scala")
| } yield file
scalaFiles: Array[java.io.File]
//Array[File]到Array[Int]的转换
scala> val forLineLengths =
| for {
| file <- filesHere
| if file.getName.endsWith(".scala")
| line <- fileLines(file)
| trimmed = line.trim
| if trimmed.matches(".*for.*")
| } yield trimmed.length
forLineLengths: Array[Int] = Array()