Scala快速入门

变量定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
val hello="Hello Scala"
val hello:String="Hello Scala"
val hello:java.lang.String="Hello Scala"
lazy val hello="Hello Scala"
val hello="Hello Scala"

val x=0x29 //十六进制定义整数
val x=41 //十进制定义整数

val doubleNumber = 3.14159 //Double类型定义,直接输入浮点数,编译器会将其自动推断为Double类型
val floatNumber=3.14159F //定义Float类型浮点数,需要在浮点数后面加F或f

val floatNumber=0.1314e1

var letter = 'A' //字符定义,用单引号(')将字符包裹

val hello = """Hello \n \t \b \\ Scala"""
//如果需要原样输出字符串中的内容,则用三个双引号"""将字符串包裹起来

var bool = true

注:

  • val 相当于Java中的final关键字修饰的变量,一旦赋值便不能更改

  • 当未指定类型时,Scala会根据实际类型进行类型推断,上面前三种方式结果相同

  • lazy关键字修饰的变量,定义时不赋值,真正使用时才赋值

  • var关键字修饰的变量,可以被重新赋值
    e也可以是大写E,0.1214e1 = 0.131410

  • e也可以是大写E,0.1214e2 = 0.13141010

函数定义

1
2
3
4
5
6
7
8
9
10
11
12
13
def max(x:Int, y:Int):Int={
if(x > y)
x
else
y
}

def sub(a:Int,b:Int)={
a-b
}
def sub(a:Int,b:Int):Unit={
a-b
}
  • def:关键字,定义一个函数

  • max:自定义的方法名

  • (x:Int, y:Int):方法名后小扩号中为参数列表

  • Int:参数后的Int为方法返回值类型

  • {…}:大扩号中为方法体

  • Scala函数返回值可以不加return,默认函数体最后一条语句为返回值

  • 函数体不指定返回值时,scala会根据实际类型进行类型推断

  • Unit关键字表示函数不存在返回值,相当于java中的void关键字

  • Scala每行语句结束后的分号可加可不加

Scala基本类型

Value type Range
Byte 8-bit
Short 16-bit
Int 32-bit
Long 64-bit
Char 16-bit
Float 32-bit
Double 64-bit
Boolean true or false
String

算术操作+ - * / %

  • 在Scala中一切操作皆方法,这意味着Scala中的一切毕为对象
  • 1+2整数求和时,编译器会将其转换为(1).+(2)执行,所以下面两种方式是相等的
    var sum =1+2
    var sum=(1).+(2)

  • 操作符重载,编译器会将其转换为(1).+(2L)执行结果等于3
    var longsum = 1 + 2L

  • Scala中可以用+ -符号来表示正负数,例如:-3+3
    var y= 1+ -3
    var y= -3+3

关系运算符

= < ⇐ ! ==

逻辑运算符

! && ||

位运算

&(按位与) |(按位或) ^(按位异或) ~(按位取反) «(左移) »(带符号右移) »>(无符号右移)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
//00000001
//00000010
//00000000
scala> 1 & 2
res0: Int = 0

//00000001
//00000010
//00000011
scala> 1 | 2
res0: Int = 3

//00000001
//1111110
scala> ~1
res1: Int = -2

//00000001
//00000010
scala> 1 << 1
res3: Int = 2

//00000001
//00000000
scala> 1 >> 1
res5: Int = 0

//00000001
//00000000
scala> 1 >>> 1
res7: Int = 0

//00000001
//00000010
//操作的结果是如果某位不同则该位为1, 否则该位为0.
scala> 1 ^ 2
res9: Int = 3

scala> 1 ^ 3
res10: Int = 2

对象比较

  • Scala中的对象比较不同于Java中的对象比较
  • Scala基于内容的比较,而Java中比较的是引用地址
  • Scala eq 方法是基于引用地址的比较
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
scala> 1==1
res16: Boolean = true

scala> 1==1.0
res17: Boolean = true

scala> val x="hello"
x: String = hello

scala> val y="hello"
y: String = hello

scala> x==y
res18: Boolean = true

scala> val x:String = new String("hello")
x: String = hello

scala> val y:String = new String("hello")
y: String = hello

scala> x==y
res20: Boolean = true

scala> x.eq(y)
res17: Boolean = false

运算符的优先级

扩号优先级最高
* / %
+ -
:
= !
< >
&

字符串的操作

var str = “hello”

  • 定义的String类型变量可以使用java中String的所有方法
  • 隐式转换:Scala把String类型转换成StringOps,其中包括了所有的immutable sequence的方法。碰到reverse,map,drop和slice方法时编译器会自动插入这个转换。
  • Scala方法的调用可以不加点“.”,直接用空格调用,并且可以省略扩号
1
2
3
4
5
6
7
8
9
10
11
12
str.indexOf(“o”)
str indexOf 'o'
str.toUpperCase
str.toLowerCase
str.reverse
str.map(_.toUpper)
str.drop(2)
str drop 2
str drop(2)
str slice(1,4)
str.slice(1,4)
….

if的使用

  • Scala会自动进行类型推断
1
2
3
4
scala> var x = if("hello"=="hello")1 else 2 
x: Int = 1
scala> var x = if("hello"=="hello")"1" else "2"
x: String = 1

while的使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def main(args: Array[String]): Unit = {
HelloScala loop 4
HelloScala loop(4)
HelloScala.loop(4)
var line=""
while((line=readLine())!="") //readLine() 读取控制台的输入
println("read:"+line)
}

def loop(x:Int)={
var a=x
while(a!=0){
a=a-1
println(a)
}
}

do while的使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
def main(args: Array[String]): Unit = {
HelloScala loop(4,2)
HelloScala.loop(4,2)

var line=""
do{
line=readLine()
println("read:"+line)
}
while(line!="")
}
def loop(x:Int,y:Int)={
var a=x
do{
a=a-y
println(a)
}
while(a!=0)
}
  • Scala具有函数式编程语方的特点,在函数式编程语方当中,一般不推荐使用var变量

  • 利用if替代while控制结构,可以减少var变量的使用,程序结构也更简单,表达能力更强

1
2
3
4
5
6
def loop(x:Int):Unit={
if(x!=0){
println(x)
loop(x-1)
}
}

for循环的使用

  1. 打印当前目录所有文件名
  • ← 生成器(generator),在执行过程中,集合files中的Array[File]的元素将依次赋值给file,file类型为File,输出时调用其toStirng方法将文件名打印出来
1
2
3
4
5
6
val files = (new java.io.File(".")).listFiles
for(file <- files )println(file)
val files = (new java.io.File(".")).listFiles
for(i <- 0 to files.length -1)println(files(i))
var a = 1 to 2
for(i <- a)println("item:"+i)
  1. for循环中加入if过滤操作
1
2
val files = (new java.io.File(".")).listFiles
for(file <- files if file.getName.endsWith("iml"))println(file)
  1. 加入多个过滤条件
1
for(file <- files if file.isFile; if file.getName.endsWith("iml")) println(file)

4.多重循环的实现

1
2
3
4
5
6
7
8
9
10
11
def main(args: Array[String]): Unit = {
grep("JAVA")
}

def fileLines(file: File) = scala.io.Source.fromFile(file).getLines.toList

def grep(pattern:String) =
for (
file <- (new File(".")).listFiles if file.getName.endsWith("iml");
line <- fileLines(file) if line.trim.contains(pattern)
) println(file + ":" + line.trim)

yield 关键字在循环中生成返回结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
def main(args: Array[String]): Unit = {
println(getFile(0))
}

def getFile =
for{
file <- (new File(".")).listFiles if file.getName.endsWith("iml")
}yield file
def main(args: Array[String]): Unit = {
for(i <- grep("orderEntry"))println(i)
}

def fileLines(file: File) =
scala.io.Source.fromFile(file).getLines.toList

def grep(pattern:String) =
for (
file <- (new File(".")).listFiles if file.getName.endsWith("iml");
line <- fileLines(file) if line.trim.contains(pattern)
) yield line.trim
//返回Array[String]

Array数组操作

定长数组Array

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Scala中的Array是以Java中的Array方式实现的 

var arr = 0 until 5
scala.collection.immutable.Range = Range 0 until 5

val arr1 = new Array[Int](10)
复杂对象类型的数组初使化值为null,数值型被初使化为0

var arr2 = Array(“aaa”,“bbb”)
定义一个数组同时赋值,这种调用方式是调用其apply方法进行数组创建操作的

arr2(1)=“test”
数组元素赋值,不同于Java,这里index的指定是用小扩号。

intArr.update(2,“test2”)
更新值

变长数组ArrayBuffer

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
scala.collection.mutable.ArrayBuffer 

var arr=ArrayBuffer[String]()
arr+=“Hello
arr+=(“Hello”,“Scala”)
+= 在尾部添加元素

arr.insert(1,“test1”,“test2”,“test3”)
arr.insertAll(3,arr)
arr.insertAll(3,arr2)
在指定位置插入数据

arr.remove(0,2)
从索引0开始,删除2个元素

arr++=Array(“hello”,“test”)
arr++=List(“value1”,“value2”)
++=用于向数组中追加内容,++=右侧可以是任何集合

arr.trimStart(2)
删除前面2个元素

arr.trimEnd(2)
删除未尾2个元素

arr.toArray
转换ArrayBuffer to Array

arr.toBuffer
转换Array to ArrayBuffer

遍历数组
to 方式
for(i ← 0 to arr.length-1)println(arr(i))

until方式
for(i ← 0 until arr.length)println(arr(i))

foreach方式
for(i ← arr)print(“\t”+i)

指定步长
for(i← 0 until (arr.length,2)) print(“\t”+arr(i))
for(i← (0 to (arr.length-1,2))) print(“\t”+arr(i))

倒序输出
for(i ← (0 until arr.length).reverse) print(“\t”+arr(i))
for(i ← (0 to arr.length -1).reverse) print(“\t”+arr(i))
for(i ← arr.reverse) print(“\t”+i)

yield返回新的数组
var arr2 = for(i ← arr) yield i+“test”
*原数组不变
*BufferArray转换后产生的仍然是BufferArray
*Array转换后产生的仍然是Array

数组求和,最大值,最小值,格式化输出,过滤掉小于3数据
val intArr = Array(1,2,3,4,5)
println(intArr.sum)
println(intArr.max)
println(intArr.min)
println(intArr.mkString)
println(intArr mkString “,”)
println(intArr.mkString(“(”,“,”,“)”))
println(intArr.dropWhile(_<3) mkString “,”)

多维数组
var multiArr = Array(Array(1,2,3),Array(4,5,6))
println(multiArr(1)(2))
for (elem ← multiArr) {println(elem mkString(“,”))}

List

List的定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
val cars = List(“bmw”,“volvo”) 
val cars = List.apply(“bmw”,“volvo”)
val nums = List(1,2,3,4,5,6,7,7,8)
var cars:List[Object]=List(“BMW”,“Volvo”)
var list= List()
var cars:List[String]=List()

采用 :: 及Nil进行列表构建
val nums = 1 :: (2 :: (3:: (4::Nil)))
相等于
val nums = List(1, 2, 3, 4)
相等于
val nums = 1::2::3::4::Nil

多重List
val cars=List(List(“BMW”,“200万”,“red”),List(“BYD”,“20万”,“white”))

*list一旦被创建,其值不能被改变
*list具有递归结构(Recursive Structure),例如链表结构
*List类型和其它集合类型一样,它具有协变性(Covariant),即对于类型ST,如果ST的子类型,则List[S]也是List[T]的子类型
*空的List,其类型为Nothing,NothingScala的继承层次中的最低层,即Nothing是任何Scala其它类型如String,Object等的子类
\* :: 操作符的优先级是从右往左的

list常用操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
判断是否为空 
cars.isEmpty

取第一个元素
cars.head

取第一个元素外的元素列表
cars.tail
cars.reverse.init

init取最后一个元素外的元素列表
cars.init
cars.reverse.tail

取最后一个
cars:last

取第二个元素
cars.tail.head

取倒数第二个元素
cars.init.last

元素倒置
cars.reverse

丢弃前N个元素,返回元素列表
cars drop 1

获取前几个元素列表
cars take 2
cars.take(2)

将列表进行分割,从Index N的位置进行分割,返回前后两个元素列表,位置N算后面的元素列表
cars.splitAt(1)
(cars.take(1),cars.drop1)

zip 返回的是List类型的元组(Tuple)
1
2
3
4
5
6
7
8
scala> val arr = List("1","6","3","5","9") 
arr: List[String] = List(1, 6, 3, 5, 9)

scala> val num = List(1,6,3,5,9)
num: List[Int] = List(1, 6, 3, 5, 9)

scala> arr zip num
res99: List[(String, Int)] = List((1,1), (6,6), (3,3), (5,5), (9,9))

插入排序算法

1
2
3
4
5
6
7
8
9
def sort(xs:List[Int]) :List[Int] ={
if(xs.isEmpty) Nil
else insert(xs.head, sort(xs.tail))
}

def insert(x:Int, xs:List[Int]) :List[Int] ={
if(xs.isEmpty || x<= xs.head) x:: xs
else xs.head :: insert(x,xs.tail)
}

List连接操作 :::

1
2
scala> List(1,2):::List(3,4)
res35: List[Int] = List(1, 2, 3, 4)

list相等判断

1
2
3
4
5
6
val arr = List(1,6,3,5,9) 
val arr1 = List("1","6","3","5","9")
aaa == arr1 //false
val arr = List("1","6","3","5","9")
val arr1 = List("1","6","3","5","9")
arr == arr1 //true

range方法,构建某一值范围内的List
val nums = List.range(2,9)
range主法,指定步长N,范围不存在的返回空List
val nums = List.range(2,100, 5)
val nums = List.range(100,20, -5)

flatten,将列表平滑成第一个元素

1
2
scala> List(List("aaa","bbb"),List("111","222")).flatten 
res34: List[String] = List(aaa, bbb, 111, 222)

concat列表链接

1
scala> List.concat(List("aaa","bbb"),List("111","222")) res32: List[String] = List(aaa, bbb, 111, 222) \\

Set

Set 不可重复,无序的集合
如果需要按添加顺序排序,可以使用LinkedHashSet实现

val set = Set(1,2,3)
val mutableSet = mutable.Set(1,2,3)

添加元i
set+5

遍历Set
for(i ← set+7)print(i)

Map

val map = Map(1 → “one”,“two” → 2,2.3 → “three”)
val mutableMap = mutable.Map(1 → “one”,“two” → 2,2.3 → “three”)
println(map)

添加元素
println(map.+(4 → “four”))

删除元素
println(map.-(“tow”))

遍历map

1
2
3
4
5
6
7
for(i<-map)println(i+"\t"+i._1+"\t"+i._2)  
map.foreach(e=>{
val (k,v)=e
println(k,v) //通过模式匹配获取元组内容
println(e._1,e._2) //直接访问元组内容

})

mutable map可以使用put添加元素
val mutableMap = mutable.Map(1 → “one”,“two” → 2,2.3 → “three”)
mutableMap.put(“four”,4)

判断key是不存在 map.contains(1) map.get(“key”)

Queue队列

immutable queue
scala> var queue=scala.collection.immutable.Queue(1,2,3)
queue: scala.collection.immutable.Queue[Int] = Queue(1, 2, 3)

出队
scala> queue.dequeue
res38: (Int, scala.collection.immutable.Queue[Int]) = (1,Queue(2, 3))

入队
scala> queue.enqueue(4)
res40: scala.collection.immutable.Queue[Int] = Queue(1, 2, 3, 4)

mutable queue
scala> var queue=scala.collection.mutable.Queue(1,2,3,4,5)
queue: scala.collection.mutable.Queue[Int] = Queue(1, 2, 3, 4, 5)

入队操作
scala> queue += 5
res43: scala.collection.mutable.Queue[Int] = Queue(1, 2, 3, 4, 5, 5)

集合方式
scala> queue ++= List(6,7,8)
res45: scala.collection.mutable.Queue[Int] = Queue(1, 2, 3, 4, 5, 5, 6, 7, 8)

Scala.collection

scala会默认导入以几个包:
import java.lang
import scala.

import Predef._

Predef对象中包含了Set、Map等的定义 在Scala中,默认使用的immutable集合,如果需要使用mutable集合,需要在在程序中import
immutable 不可变的集合,一量被创建,便不能被改变,添加、删除、更新操作返回的是新的集合,原集合保持不变 mutable 可变的集合,可以更新或修改,添加、删除、修改元素将作用于原集合

scala.collection包中的集合类层次结构如下图:

img

scala.collection.immutable包中的类层次结构:

img

scala.collection.mutable包中的类层次结构:
img

可变集合与不可变集合对应关系:

img

函数字面量(值函数)

函数字面量(function literal),也称值函数(function values),指的是函数可以赋值给变量。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
val increase=(x:Int)=>x+1
//=>左侧的表示输入参数,右侧的表示方法体
//等同于
def increase(x:Int)=x+1

//方法体中多个语句则使用{}
val increase=(x:Int)=>{
println("begin")
println("end")
x+1
}
//数组的map方法中调用(写法1)
//写法1
println(Array(1,2,3).map(increase).mkString(“,”))
//写法2 匿名函数写法
println(Array(1,2,3).map((x:Int)=>x+1) mkString “,”)

函数简化

大扩号中只有一行操作时,大扩号可以省掉, 方法的调用可以省略“.”,用空格代替
*参数类型推断写法

1
2
println(Array(1,2,3) map((x)=>x+1) mkString ",")
println(Array(1,2,3) map((x)=>x+1) mkString(","))

*函数只有一个参数的话,可以省略()

1
2
scala> Array(1,2,3,4) map{x=>x+1} mkString(",")
res28: String = 2,3,4,5

*如果参数右边只出现一次,则可以进一步简化

1
2
scala> Array(1,2,3,4) map{_+1} mkString(",")
res29: String = 2,3,4,5

*值函数简化

1
2
val fun1=1+(_:Int)
val fun2:(Double)=>Double=1+_

*函数参数,即将一个函数做为参数传入

1
2
3
4
5
def convertIntToString(f:(Int)=>String)=f(4)

def multiply(factor:Double)=(x:Double)=>factor*x
var b = multiply(4)
println(b(1))

函数闭包(Closure)

(x:Int)⇒x+more,这里的more是一个自由变量(Free Variable),more是一个没有指定含义的不定变量
而x的类型确定,值在函数调用的时候被赋值,称这种变量为绑定变量(Bound Variable)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
(x:Int)=>x+more 

var more=3
var fun = (x:Int)=>x+more

more =10
println(fun(1))
println(fun(13))

more =10.87
println(fun(1))
println(fun(13))
var sum=0
val list = List(1,2,3,4,5,6,7,88,9)
list.foreach(sum+=_)

*像这种运行时确定more类型及值的函数称为闭包,more是个自由变量,在运行时值和类型得以确定,这是一个由开放(free)到封闭的过程。

0%