动态

详情 返回 返回

Scala的基本使用 - 动态 详情

@

目錄
  • Scala的基本使用
    • 一、基礎語法
      • 1.1 變量
        • 1.1.1 var和val
        • 1.1.2 自動類型推斷
      • 1.2 數據類型
        • 1.2.1 基礎數據類型
        • 1.2.2 增強數據類型
      • 1.3 操作符
    • 二、流程控制
      • 2.1 if表達式
      • 2.2 語句終結符
      • 2.3 循環
        • 2.3.1 for循環
        • 2.3.2 這裏面的to可以換成until
        • 2.3.3 for循環針對字符串還可以用
          • 2.3.4 注意花括號
        • 2.3.5 while循環
      • 2.4 高級for循環
        • 2.4.1 if守衞模式
        • 2.4.2 for推導式
    • 三、Scala的集合體系
      • 3.1 集合體系
      • 3.2 集合分類
      • 3.3Set集合
        • 3.3.1創建集合
          • 不可變集合
          • 可變集合
        • 3.3.2 HashSet
        • 3.3.3LinkedHashSet
        • 3.3.4 SortedSet
      • 3.4 List集合
        • 3.4.1 創建
        • 3.4.2 獲取數組元素
      • 3.5 ListBuffer
        • 3.5.1 動態增加或者移除元素
        • 3.5.2 遍歷ListBuffer
      • 3.6 Map集合
        • 3.6.1創建Map
          • 創建一個不可變的Map
          • 創建一個可變的Map
          • 還有一種創建Map的簡易方式,這種方式創建的是不可變Map
        • 3.6.2 查詢
          • 一般查詢
          • key不存在處理
          • getOrElse函數
        • 3.6.3 修改
          • 更新map中的元素
          • 增加多個元素
          • 移除元素
        • 3.6.4 遍歷
          • 遍歷map的entrySet
          • 遍歷map的key
          • 遍歷map的value
        • 3.6.5 最後看一下Map的幾個子類
      • 3.7 Array
      • 3.8 ArrayBuffer
        • 3.8.1 初始化
        • 3.8.2 添加元素
        • 3.8.3 指定位置插入元素
        • 3.8.4 移除元素
        • 3.8.5 Array與ArrayBuffer的轉換
      • 3.9 數組常見操作
        • 3.9.1 遍歷
        • 3.9.2 求和、求最大值
        • 3.9.3 數組排序
      • 3.10 Tuple
      • 3.11 總結
        • 3.11.1 可變集合
        • 3.11.2 不可變集合
        • 3.11.3 可變+不可變集合
        • 3.11.4 還有兩個編外人員:
    • 四、Scala中函數的使用
      • 4.1 函數的定義
        • 4.1.1 定義函數
        • 4.1.2 函數的返回值
        • 4.1.3 區別
        • 4.1.4 單行函數
        • 4.1.5 多行函數
      • 4.2 函數的參數
        • 4.2.1 默認參數
          • scala實現
          • java實現
        • 4.2.2 帶名參數
        • 4.2.3 可變參數
      • 4.3 過程-特殊的函數
        • 4.3.1 定義
        • 4.3.2 寫法
      • 4.4 lazy
        • 4.4.1 使用場景

Scala的基本使用

一、基礎語法

1.1 變量

1.1.1 var和val

Scala中的變量分為兩種:
可變var:可以隨時修改var聲明的變量的值
不可變val:val聲明的變量,值不能被修改,否則會報錯:error: reassignment to val

scala> var a = 1
a: Int = 1
scala> a = 2
a: Int = 2
scala> val b = 1
b: Int = 1
scala> b = 2
<console>:8: error: reassignment to val
       b = 2
       ^

1.1.2 自動類型推斷

無論聲明val變量,還是聲明var變量,都可以手動指定變量的類型;如果不指定,Scala會自動根據值,進行類型推斷

scala> val c = 1
c: Int = 1

scala> val c: Int = 1
c: Int = 1

1.2 數據類型

1.2.1 基礎數據類型

Byte、Char、Short、Int、Long、Float、Double、Boolean

1.2.2 增強數據類型

StringOps、RichInt、RichDouble、RichChar
增強版數據類給基本數據類型增加了上百種增強的功能

1.3 操作符

Scala的算術操作符與Java的算術操作符沒有什麼區別

比如+、-、*、/、%等,以及&、|、^、>>、<<等

注意: Scala中沒有提供++、—–操作符

我們只能使用+和-,比如count = 1,count++是錯誤的,必須寫做count += 1

二、流程控制

2.1 if表達式

在Scala中, IF表達式是由返回值的,就是if或者else中最後一行語句返回的值

2.2 語句終結符

Scala默認不需要語句終結符,它將每一行作為一個語句

如果一行要放多條語句,則前面的語句必須使用語句終結符
語句終結符和Java中的一樣,就是我們平時使用的分號

scala> val age = 20; if(age > 18) 1 else 0
age: Int = 20
res0: Int = 1

2.3 循環

2.3.1 for循環

for循環本身的特性就沒什麼好説的了,直接上案例

scala> :paste
// Entering paste mode (ctrl-D to finish)

val n = 10
for(i <- 1 to n)
println(i)

// Exiting paste mode, now interpreting.

1
2
3
4
5
6
7
8
9
10
n: Int = 10

2.3.2 這裏面的to可以換成until

scala> :paste
// Entering paste mode (ctrl-D to finish)

val n = 10
for(i <- 1 until 10)
println(i)

// Exiting paste mode, now interpreting.

1
2
3
4
5
6
7
8
9
n: Int = 10

to 和 until 其實都是函數,一個是閉區間,一個是開區間

2.3.3 for循環針對字符串還可以用

scala> for(c <- "hello scala") println(c)
h
e
l
l
o

s
c
a
l
a
2.3.4 注意花括號

我在for循環後面沒有使用花括號,都省略了,主要是因為for循環的循環體代碼就只有一行,如果有多行,就需要使用花括號了,否則,最終執行的結果就不是我們想要的
沒有使用{}

scala> :paste
// Entering paste mode (ctrl-D to finish)

for(i <- 1 to 5)
println(i)
println("hehe")

// Exiting paste mode, now interpreting.

1
2
3
4
5
hehe

使用{}

scala> :paste
// Entering paste mode (ctrl-D to finish)

for(i <- 1 to 5)
{
println(i)
println("hehe")
}

// Exiting paste mode, now interpreting.

1
hehe
2
hehe
3
hehe
4
hehe
5
hehe

2.3.5 while循環

它的用法和java中的while也是很像的,主要看一下語法層面的區別

scala> :paste
// Entering paste mode (ctrl-D to finish)

var n = 10
while(n>0){
println(n)
n -= 1
}

// Exiting paste mode, now interpreting.

10
9
8
7
6
5
4
3
2
1
n: Int = 0

2.4 高級for循環

2.4.1 if守衞模式

if守衞模式,假設我們想要獲取1~10之間的所有偶數,使用普通的for循環,需要把每一個數字都循環出來,然後判斷是否是偶數
如果在for循環裏面使用if守衞,可以在循環的時候就執行一定的邏輯,判斷數值是否是偶數

scala> for(i <- 1 to 10 if i % 2 == 0) println(i)
2
4
6
8
10

2.4.2 for推導式

for推導式,一個典型例子是構造集合
我們在使用for循環迭代數字的時候,可以使用yield指定一個規則,對迭代出來的數字進行處理,並且創建一個新的集合

scala> for(i <- 1 to 10) yield i *2
res16: scala.collection.immutable.IndexedSeq[Int] = Vector(2, 4, 6, 8, 10, 12, 14, 16, 18, 20)

三、Scala的集合體系

3.1 集合體系

3.2 集合分類

Scala中的集合是分成可變和不可變兩類集合的

  • 其中可變集合就是説,集合的元素可以動態修改
  • 而不可變集合就是説,集合的元素在初始化之後,就無法修改了
    可變集合:在scala.collection.mutable這個包下面
    不可變集合:在scala.collection.immutable這個包下面

我們在創建集合的時候,如果不指定具體的包名,默認會使用不可變集合

3.3Set集合

Set代表一個沒有重複元素的集合
Set集合分為可變的和不可變的集合,默認情況下使用的是不可變集合

3.3.1創建集合

不可變集合
scala> val s = Set(1,2,3)
s: scala.collection.immutable.Set[Int] = Set(1, 2, 3)
可變集合
scala> val s = scala.collection.mutable.Set(1,2,3)
s: scala.collection.mutable.Set[Int] = Set(1, 2, 3)

scala> s += 4
res34: s.type = Set(1, 2, 3, 4)

3.3.2 HashSet

HashSet集合分為 可變和不可變集合

scala> val s = new scala.collection.mutable.HashSet[Int]()
s: scala.collection.mutable.HashSet[Int] = Set()

scala> s +=1
res35: s.type = Set(1)

scala> s +=2
res36: s.type = Set(1, 2)

scala> s +=5
res38: s.type = Set(1, 5, 2)

3.3.3LinkedHashSet

LinkedHashSet 只有可變的,沒有不可變的

scala> val s = new scala.collection.mutable.LinkedHashSet[Int]()
s: scala.collection.mutable.LinkedHashSet[Int] = Set()

scala> s +=1
res42: s.type = Set(1)

scala> s +=2
res43: s.type = Set(1, 2)

scala> s +=5
res44: s.type = Set(1, 2, 5)

3.3.4 SortedSet

SortedSet分為 可變和不可變集合
SortedSet集合中的元素是按照元素的字典順序排序的

scala> val s = scala.collection.mutable.SortedSet[String]()
s: scala.collection.mutable.SortedSet[String] = TreeSet()

scala> s +=("c")
res45: s.type = TreeSet(c)

scala> s +=("a")
res46: s.type = TreeSet(a, c)

scala> s +=("b")
res47: s.type = TreeSet(a, b, c)

3.4 List集合

List代表一個不可變的列表

3.4.1 創建

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

3.4.2 獲取數組元素

head:表示獲取List中的第一個元素
tail:表示獲取List中第一個元素之後的所有元素
那其實head和tail就可以獲取list中的所有元素了

scala> l.head
res49: Int = 1

scala> l.tail
res51: List[Int] = List(2, 3, 4)

通過::操作符,可以將head和tail的結果合併成一個List

scala> l.head :: l.tail
res52: List[Int] = List(1, 2, 3, 4)

3.5 ListBuffer

3.5.1 動態增加或者移除元素

scala> val lb = scala.collection.mutable.ListBuffer[Int]()
lb: scala.collection.mutable.ListBuffer[Int] = ListBuffer()

scala> lb +=1
res56: lb.type = ListBuffer(1)

scala> lb +=2
res57: lb.type = ListBuffer(1, 2)

scala> lb +=5
res58: lb.type = ListBuffer(1, 2, 5)

scala> lb -=5
res59: lb.type = ListBuffer(1, 2)

3.5.2 遍歷ListBuffer

scala> for(i <- lb) println(i)
1
2

3.6 Map集合

Map是一種可迭代的鍵值對(key/value)結構
Map分為可變和不可變,默認情況下使用的是不可變Map

3.6.1創建Map

創建一個不可變的Map
scala> val ages = Map("jack"->30,"tom"->25,"jessic"->23)
ages: scala.collection.immutable.Map[String,Int] = Map(jack -> 30, tom -> 25, jessic -> 23)

scala> ages("jack")
res100: Int = 30
創建一個可變的Map
scala> val ages = scala.collection.mutable.Map("jack"->30,"tom"->25,"jessic"->23)
ages: scala.collection.mutable.Map[String,Int] = Map(jessic -> 23, jack -> 30, tom -> 25)

scala> ages("jack")
res101: Int = 30
還有一種創建Map的簡易方式,這種方式創建的是不可變Map
scala> val ages = Map(("jack",30),("tom",25),("jessic"->23))
ages: scala.collection.immutable.Map[String,Int] = Map(jack -> 30, tom -> 25, jessic -> 23)

3.6.2 查詢

一般查詢
scala> val ages = scala.collection.mutable.Map(("jack",30),("tom",25),("jessic"->23))
ages: scala.collection.mutable.Map[String,Int] = Map(jessic -> 23, jack -> 30, tom -> 25)

scala> val age = ages("jack")
age: Int = 30

scala> val age = ages("jack1")
java.util.NoSuchElementException: key not found: jack1
key不存在處理

獲取指定key對應的value,如果key不存在,會報錯
使用if-else語句,如果指定的key不存在,則返回一個默認值

scala> val age = if (ages.contains("jack1")) ages("jack1") else 0
age: Int = 0
getOrElse函數

map中還有一個getOrElse函數
建議後期從map中獲取數據都使用這個getOrElse函數

scala> val age = ages.getOrElse("jack1", 0)
age: Int = 0

scala> val age = ages.getOrElse("jack", 0)
age: Int = 30

3.6.3 修改

更新map中的元素
scala> ages("jack") = 31

scala> ages
res104: scala.collection.mutable.Map[String,Int] = Map(jessic -> 23, jack -> 31, tom -> 25)
增加多個元素
scala> ages += ("hehe" -> 35, "haha" -> 40)
res105: ages.type = Map(hehe -> 35, jessic -> 23, jack -> 31, tom -> 25, haha -> 40)
移除元素
scala> ages -= "hehe"
res106: ages.type = Map(jessic -> 23, jack -> 31, tom -> 25, haha -> 40)

3.6.4 遍歷

遍歷map的entrySet
scala> for ((key, value) <- ages) println(key + " " + value)
jessic 23
jack 31
tom 25
haha 40
遍歷map的key
scala> for (key <- ages.keySet) println(key)
jessic
jack
tom
haha
遍歷map的value
scala> for (value <- ages.values) println(value)
23
31
25
40

3.6.5 最後看一下Map的幾個子類

HashMap、SortedMap和LinkedHashMap

HashMap:是一個按照key的hash值進行排列存儲的map
SortedMap:可以自動對Map中的key進行排序【有序的map】
LinkedHashMap:可以記住插入的key-value的順序
HashMap分為可變和不可變的,沒有什麼特殊之處
在這主要演示一下SortedMap和LinkedHashMap
SortedMap是不可變的

scala> val ages = scala.collection.immutable.SortedMap("b" -> 30, "a" -> 15, "c" -> 25)
ages: scala.collection.immutable.SortedMap[String,Int] = Map(a -> 15, b -> 30, c -> 25)

scala> ages
res112: scala.collection.immutable.SortedMap[String,Int] = Map(a -> 15, b -> 30, c -> 25)

LinkedHashMap是可變的

scala> val ages = new scala.collection.mutable.LinkedHashMap[String, Int]()
ages: scala.collection.mutable.LinkedHashMap[String,Int] = Map()

scala> ages("b")=30

scala> ages("a")=15

scala> ages("c")=25

scala> ages
res116: scala.collection.mutable.LinkedHashMap[String,Int] = Map(b -> 30, a -> 15, c -> 25)

3.7 Array

Scala中Array的含義與Java中的數組類似,長度不可變,數組初始化後,長度就固定下來了,而且元素全部根據其類型進行初始化,可以直接使用Array()創建數組,元素類型自動推斷

3.8 ArrayBuffer

Scala中ArrayBuffer與Java中的ArrayList類似,長度可變
ArrayBuffer:支持添加元素、移除元素
如果不想每次都使用全限定名,則可以預先導入ArrayBuffer類

scala> import scala.collection.mutable.ArrayBuffer
import scala.collection.mutable.ArrayBuffer

3.8.1 初始化

使用ArrayBuffer()的方式可以創建一個空的ArrayBuffer

scala> val b = new ArrayBuffer[Int]()
b: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer()

3.8.2 添加元素

使用+=操作符,可以添加一個元素,或者多個元素
b += 1 或者 b += (2, 3, 4, 5)

scala> b += 1
res69: b.type = ArrayBuffer(1)

scala> b += (2, 3, 4, 5)
res70: b.type = ArrayBuffer(1, 2, 3, 4, 5)

3.8.3 指定位置插入元素

使用insert()函數可以在指定位置插入元素,但是這種操作效率很低,因為需要移動指定位置後的所有元素
向3號角標的位置添加一個元素 30

scala> b.insert(3,30)

scala> b
res72: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3, 30, 4, 5)

3.8.4 移除元素

使用remove()函數可以移除指定位置的元素
移除1號角標的元素

scala> b.remove(1)
res73: Int = 2

scala> b
res74: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 3, 30, 4, 5)

3.8.5 Array與ArrayBuffer的轉換

Array與ArrayBuffer可以互相進行轉換

b.toArray:ArrayBuffer轉Array
a.toBuffer:Array轉ArrayBuffer

3.9 數組常見操作

3.9.1 遍歷

scala> val b=ArrayBuffer(1, 2, 3, 4, 5)
b: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3, 4, 5)

scala>  for(i <- b) println(i)
1
2
3
4
5

scala> for(i <- 0 until b.length ) println(b(i))
1
2
3
4
5

3.9.2 求和、求最大值

scala> val a = Array(3, 2, 1, 4, 5)
a: Array[Int] = Array(3, 2, 1, 4, 5)

scala> val sum = a.sum
sum: Int = 15

scala> val max = a.max

3.9.3 數組排序

scala> scala.util.Sorting.quickSort(a)

scala> a
res99: Array[Int] = Array(1, 2, 3, 4, 5)

3.10 Tuple

Tuple:稱之為元組,它與Array類似,都是不可變的,但與數組不同的是元組可以包含不同類型的元素
Tuple中的元素角標從 1 開始

目前 Scala 支持的元組最大長度為 22 ,對於更大長度可以使用集合或數組

scala> val t = (1, 3.14, "hehe")
t: (Int, Double, String) = (1,3.14,hehe)

scala> t._1
res117: Int = 1

scala> t._3
res118: String = hehe

3.11 總結

3.11.1 可變集合

LinkedHashSet、ListBuffer、ArrayBuffer、LinkedHashMap

3.11.2 不可變集合

List、SortedMap

3.11.3 可變+不可變集合

Set、HashSet、SortedSet、Map、HashMap

3.11.4 還有兩個編外人員:

Array、Tuple
Array:長度不可變,裏面的元素可變
Tuple:長度不可變,裏面的元素也不可變

四、Scala中函數的使用

4.1 函數的定義

4.1.1 定義函數

在Scala中定義函數需要使用 def 關鍵字,函數包括函數名、參數、函數體

4.1.2 函數的返回值

Scala要求必須給出函數所有參數的類型,但是函數返回值的類型不是必須的,因為Scala可以自己根據函數體中的表達式推斷出返回值類型。

4.1.3 區別

函數中最後一行代碼的返回值就是整個函數的返回值,不需要使用return,這一點與Java不同,java中函數的返回值是必須要使用return的

4.1.4 單行函數

scala> def sayHello(name: String) = print("Hello, " + name)
sayHello: (name: String)Unit

scala> sayHello("Scala")
Hello, Scala

4.1.5 多行函數

scala> :paste
// Entering paste mode (ctrl-D to finish)

def sayHello(name: String, age: Int) = {
println("My name is "+name+",age is "+age)
age
}

// Exiting paste mode, now interpreting

sayHello: (name: String, age: Int)Int

scala> sayHello("Scala",18)
My name is Scala,age is 18
res120: Int = 18

4.2 函數的參數

4.2.1 默認參數

在Scala中,有時候我們調用某些函數時,不希望給出參數的具體值,而是希望使用參數自身默認的值,此時就需要在定義函數時使用默認參數。
如果給出的參數不夠,則會從左往右依次應用參數。

scala> def sayHello(fName: String, mName: String = "mid", lName: String = "last") = fName + " " + mName + " " + lName
sayHello: (fName: String, mName: String, lName: String)String

scala> sayHello("zhang","san")
res122: String = zhang san last
scala實現
def sayHello(name: String ="defaultName" , age: Int = 18) {
  println("Hello, " + name + ", your age is " + age)
}
java實現
public void sayHello(String name, int age) {
  if(name == null) {
    name = "defaultName"
  }
  if(age == 0) {
    age = 18
  }
  System.out.println("Hello, " + name + ", your age is " + age)
}

4.2.2 帶名參數

在調用函數時,也可以不按照函數定義的參數順序來傳遞參數,而是使用帶名參數的方式來傳遞。

scala> def sayHello(fName: String, mName: String = "mid", lName: String = "last") = fName + " " + mName + " " + lName
sayHello: (fName: String, mName: String, lName: String)String

scala> sayHello(fName = "Mick", lName = "Tom", mName = "Jack")
res127: String = Mick Jack Tom

4.2.3 可變參數

在Scala中,有時我們需要將函數定義為參數個數可變的形式,則此時可以使用變長參數來定義函數。

scala> :paste
// Entering paste mode (ctrl-D to finish)

def sum(nums: Int*) = {
  var res = 0
  for (num <- nums) res += num
  res
}

// Exiting paste mode, now interpreting.

sum: (nums: Int*)Int

scala> sum(1,2,3,4,5)
res129: Int = 15

4.3 過程-特殊的函數

4.3.1 定義

定義函數時,如果函數體直接在花括號裏面而沒有使用=連接,則函數的返回值類型就是Unit,這樣的函數稱之為過程

過程通常用於不需要返回值的函數

4.3.2 寫法

過程還有一種寫法,就是將函數的返回值類型顯式定義為Unit
比較一下這四種寫法的區別
函數:

def sayHello(name: String) = "Hello, " + name
def sayHello(name: String): String = "Hello, " + name

過程:

def sayHello(name: String) {  "Hello, " + name }
def sayHello(name: String): Unit = "Hello, " + name

4.4 lazy

將一個變量聲明為lazy,則只有在第一次使用該變量時,變量對應的表達式才會發生計算

4.4.1 使用場景

什麼場景下需要使用lazy特性呢?
這種特性對於特別耗時的操作特別有用,比如打開文件這個操作。

scala> import scala.io.Source._
import scala.io.Source._

scala> lazy val lines = fromFile("D://test.txt").mkString
lines: String = <lazy>

即使D://test.txt文件不存在,代碼也不會報錯,只有變量使用時才會報錯,這就是lazy這個特性。

scala> lines
java.io.FileNotFoundException: D:\test.txt (系統找不到指定的文件。)
.......

Add a new 评论

Some HTML is okay.