欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Scala基礎(chǔ)語法總結(jié)

 更新時(shí)間:2023年11月01日 11:22:03   投稿:wdc  
這篇文章主要介紹了Scala基礎(chǔ)語法總結(jié),需要的朋友可以參考下

一、變量

val/var 變量名稱:變量類型 = 初始值

注意:

  • val定義的是不可重新賦值的變量(值不可修改)

  • var定義的是可重新賦值的變量(值可以修改)

  • scala中聲明變量是變量名稱在前,變量類型在后,跟java是正好相反

  • scala的語句最后不需要添加分號(hào)、、

 惰性變量

  • Scala中使用==關(guān)鍵字lazy==來定義惰性變量,實(shí)現(xiàn)延遲加載(懶加載)。

  • 惰性變量只能是不可變變量,并且只有在調(diào)用惰性變量時(shí),才會(huì)去實(shí)例化這個(gè)變量。

  • 語法格式

lazy val 變量名 = 表達(dá)式

 二、數(shù)據(jù)類型

基礎(chǔ)類型類型說明
Byte8位帶符號(hào)整數(shù)
Short16位帶符號(hào)整數(shù)
Int32位帶符號(hào)整數(shù)
Long64位帶符號(hào)整數(shù)
Char16位無符號(hào)Unicode字符
StringChar類型的序列(字符串)
Float32位單精度浮點(diǎn)數(shù)
Double64位雙精度浮點(diǎn)數(shù)
Booleantrue或false

1. scala中所有的類型都使用大寫字母開頭,說明是它是“類”
2. 整形使用Int而不是Integer
3. scala中定義變量可以不寫類型,讓scala編譯器自動(dòng)推斷 

三、scala中的條件表達(dá)式

1、if表達(dá)式

這個(gè)和java差不多,可以加括號(hào),或者不加括號(hào)

  def main(args: Array[String]): Unit = {
     val x:Int=2
     if (x>10) println(x)
     else println(x+x)
}

打印為2

2、塊表達(dá)式

定義變量時(shí)用 {} 包含一系列表達(dá)式,其中塊的最后一個(gè)表達(dá)式的值就是塊的值

  def main(args: Array[String]): Unit = {

    val x = 0
    val result = {
      val y = x + 10
      val z = y + "-hello"
      val m = z + "-kaikeba"
      "over"
    }
    println(result)
}

打印結(jié)果

over

Process finished with exit code 0

返回值就是m了 

  def main(args: Array[String]): Unit = {
    val x = 0
    val result = {
      val y = x + 10
      val z = y + "-hello"
      val m = z + "-kaikeba"
      m
    }
    println(result)
}

打印結(jié)果

10-hello-kaikeba

四、循環(huán)

在scala中,可以使用for和while,但一般推薦使用for表達(dá)式,因?yàn)閒or表達(dá)式語法更簡(jiǎn)潔

for (i <- 表達(dá)式/數(shù)組/集合){
    //表達(dá)式
}

1、簡(jiǎn)單for循環(huán)

def main(args: Array[String]): Unit = {
    var nums=1 to 10
    //for循環(huán)
    for(i <- nums) println(i)
}

2、雙層for循環(huán)

  def main(args: Array[String]): Unit = {

    //雙層for循環(huán)
    for (i <- 1 to 3; j <- 1 to 3)
      println(i * 10 + j)
}

打印的值為

11
12
13
21
22
23
31
32
33

3、守衛(wèi):在for表達(dá)式中可以添加if判斷語句,這個(gè)if判斷稱為守衛(wèi)

 def main(args: Array[String]): Unit = {
//    守衛(wèi)
    var nums = 1 to 10
    for (i <- nums if i>5 ) println(i)
}

打印的值為: 

6
7
8
9
10

4、yield表達(dá)式 

在for循環(huán)體中,以yield表達(dá)式開始,這類循環(huán)能構(gòu)建出一個(gè)新的集合,我們把這類循環(huán)稱為推導(dǎo)式

def main(args: Array[String]): Unit = {

    // for推導(dǎo)式:for表達(dá)式中以yield開始,該for表達(dá)式會(huì)構(gòu)建出一個(gè)集合
    val v = for(i <- 1 to 5) yield i * 10
    //打印集合v的第一個(gè)元素
    println(v(0))
}

打印的值為

10

五、while循環(huán)

while(返回值為布爾類型的表達(dá)式){
    //表達(dá)式
}

六、方法

def methodName (參數(shù)名:參數(shù)類型, 參數(shù)名:參數(shù)類型) : [return type] = {
    // 方法體:一系列的代碼
}
  • 參數(shù)列表的參數(shù)類型不能省略

  • 返回值類型可以省略,由scala編譯器自動(dòng)推斷

  • 返回值可以不寫return,默認(rèn)就是{}塊表達(dá)式的值  

  • 注意:

  • 如果定義遞歸方法,必須指定返回值類型

  • 示例:(方法三)

  • 定義遞歸方法(求階乘)

  • 10 * 9 * 8 * 7 * 6 * ... * 1

  //方法一
  def yy(i: Int = 10, u: Int = 8): Int = {
    return i + u;
  }

  //方法二
  def tt(i: Int) = i * i


  /**
   * 遞歸必須添加返回值參數(shù)
   *
   * @param x
   * @return
   */
  //方法三
  def m1(x: Int): Int = {
    if (x == 1) 1
    else x * m1(x - 1)
  }

  /**
   * 參數(shù)值加*,可以傳遞多個(gè)參數(shù)
   *
   * @param num
   * @return
   */
  //    方法四
  def add(num: Int*) = num.sum

  def main(args: Array[String]): Unit = {
    
        println(yy(1))
        println(tt(8))
        println(m1(10))
        println(add(1,2,3))
}

打印的值為

9
64
3628800
6

6、函數(shù)

  • 函數(shù)在scala中屬于頭等公民

    • 數(shù)字能做的事,函數(shù)也可以

    • 數(shù)字可以作為參數(shù),所以函數(shù)也可以作為其他方法或函數(shù)的參數(shù)

    • 數(shù)字可以作為返回值,所以函數(shù)也可以作為其他方法或函數(shù)的返回值

    • 數(shù)字可以賦值給一個(gè)變量,所以函數(shù)也可以賦值給一個(gè)變量

  • scala支持函數(shù)式編程,將來編寫Spark/Flink程序中,會(huì)大量使用到函數(shù)

  • 語法

val 函數(shù)變量名 = (參數(shù)名:參數(shù)類型, 參數(shù)名:參數(shù)類型....) => 函數(shù)體

注意

  • 函數(shù)是一個(gè)對(duì)象(變量)

  • 類似于方法,函數(shù)也有輸入?yún)?shù)和返回值

  • 函數(shù)定義不需要使用def定義

  • 無需指定返回值類型

 val add2 = (x: Int, y: Int) => x * y
  def main(args: Array[String]): Unit = {
        println(add2(2,4))
}

 打印的值為

8

方法和函數(shù)的區(qū)別

  • 方法是隸屬于類或者對(duì)象的,在運(yùn)行時(shí),它是加載到JVM的==方法區(qū)==中

  • 可以將函數(shù)對(duì)象賦值給一個(gè)變量,在運(yùn)行時(shí),它是加載到JVM的==堆內(nèi)存==中

  • 函數(shù)是一個(gè)對(duì)象,繼承自FunctionN,函數(shù)對(duì)象有apply,curried,toString,tupled這些方法,而方法則沒有

方法轉(zhuǎn)換為函數(shù)

  • 有時(shí)候需要將方法轉(zhuǎn)換為函數(shù),作為變量傳遞,就需要將方法轉(zhuǎn)換為函數(shù)

  • 使用 即可將方法轉(zhuǎn)換為函數(shù)(記得空格)

  •  //方法三
      def m1(x: Int): Int = {
        if (x == 1) 1
        else x * m1(x - 1)
      }
      val hanshu=m1 _;
      def main(args: Array[String]): Unit = {
    
        println(hanshu(10))
      }

    打印的結(jié)果 

  • 3628800

    7、數(shù)組

  • scala中數(shù)組的概念是和Java類似,可以用數(shù)組來存放同類型的一組數(shù)據(jù)

  • scala中,有兩種數(shù)組,一種是定長(zhǎng)數(shù)組,另一種是變長(zhǎng)數(shù)組 

(1)、定長(zhǎng)數(shù)組

  • 定長(zhǎng)數(shù)組指的是數(shù)組的長(zhǎng)度不允許改變

  • 數(shù)組的元素可以改變

demo如下 

def main(args: Array[String]): Unit = {
    val a = new Array[Int](10)
    println(a)
    a(0)=98
    println(a(0))
    println(a(1))
    println(a.length)
  }

 打印的值為:

[I@ea4a92b
98
0
10

(2)、變長(zhǎng)數(shù)組

  • 變長(zhǎng)數(shù)組指的是數(shù)組的長(zhǎng)度是可變的,可以往數(shù)組中添加、刪除元素

  • 創(chuàng)建變長(zhǎng)數(shù)組,需要提前導(dǎo)入ArrayBuffer類

import scala.collection.mutable.ArrayBuffer

語法

  • 創(chuàng)建空的ArrayBuffer變長(zhǎng)數(shù)組

  • val/var a = ArrayBuffer[元素類型]()

    創(chuàng)建帶有初始元素的ArrayBuffer

  • val/var a = ArrayBuffer(元素1,元素2,元素3....)

    變長(zhǎng)數(shù)組的增刪改操作

  • 使用+=添加元素

  • 使用-=刪除元素

  • 使用++=追加一個(gè)數(shù)組到變長(zhǎng)數(shù)組

demo如下 

  def main(args: Array[String]): Unit = {
    //變長(zhǎng)數(shù)組
    val a = ArrayBuffer[String]();
    a+=("test")
    a+=("張三")
    a++=Array("妞兒","所以算是")
    println(a(3))
    println(a.size)
  }
}

打印的值為

所以算是
4

(3)、遍歷數(shù)組

可以使用以下兩種方式來遍歷數(shù)組:

  • 使用==for表達(dá)式== 直接遍歷數(shù)組中的元素

  • 使用 ==索引== 獲得數(shù)組中的元素

for(i <- a) println(i)
/0 to n    ——包含0,也包含n
for(i <- 0 to a.length -1 ) println(a(i))
//0 until n ——生成一系列的數(shù)字,包含0,不包含n
for(i <- 0 until a.length) println(a(i))

(4)、數(shù)組常用操作

scala中的數(shù)組封裝了豐富的計(jì)算操作,將來在對(duì)數(shù)據(jù)處理的時(shí)候,不需要我們自己再重新實(shí)現(xiàn)。

  • 求和——sum方法

  • 求最大值——max方法

  • 求最小值——min方法

  • 排序——sorted方法

 def main(args: Array[String]): Unit = {

    val array = Array(1,3,4,2,5)
    println("求和:"+array.sum)
    println("最大值:"+array.max)
    println("最小值:"+array.min)
    println("排序(獲取一個(gè)新數(shù)組,并翻轉(zhuǎn)):"+array.sorted.reverse(0))

  }

 打印如下

求和:15
最大值:5
最小值:1
排序(獲取一個(gè)新數(shù)組,并翻轉(zhuǎn)):5

8、元組 

元組可以用來包含一組不同類型的值。例如:姓名,年齡,性別,出生年月。

元組的元素是不可變的。

1、定義元組

使用括號(hào)來定義元組

val/var 元組變量名稱 = (元素1, 元素2, 元素3....)

使用箭頭來定義元素(元組只有兩個(gè)元素 )

val/var 元組 = 元素1 -> 元素2

2、訪問元組

  • 使用 _1、_2、_3....來訪問元組中的元素

  • 元組的index從1開始,_1表示訪問第一個(gè)元素,依次類

  def main(args: Array[String]): Unit = {
    val a = (1, "張三", 20, "北京市")
    val b = 1 -> 2
    println(a._1)
    println(a._4)
    println(b._1)
  }

 打印的值為

1
北京市
1

9、映射Map

  • Map可以稱之為映射。它是由鍵值對(duì)組成的集合。scala當(dāng)中的Map集合與java當(dāng)中的Map類似,也是key,value對(duì)形式的。

  • 在scala中,Map也分為不可變Map和可變 Map。

(1)、不可變map

  定義語法

val/var map = Map(鍵->值, 鍵->值, 鍵->值...)    // 推薦這種寫法,可讀性更好 
val/var map = Map((鍵, 值), (鍵, 值), (鍵, 值), (鍵, 值)...)
def main(args: Array[String]): Unit = {
    val map1 = Map("zhangsan"->30, "lisi"->40)
    val map2 = Map(("zhangsan", 30), ("lisi", 30))
    println(map1("lisi"))
    println(map2("zhangsan"))
  }

打印的值為

40
30

(2)、可變Map

1、導(dǎo)包

import scala.collection.mutable.Map
  def main(args: Array[String]): Unit = {

    val map3 = Map("zhangsan" -> 30, "lisi" -> 40)
    //修改一個(gè)
    map3("zhangsan") = 50
    println("修改的" + map3)
    //添加一個(gè)
    map3 += ("yy" -> 22)
    println("添加的" + map3)
    //刪去一個(gè)
    map3 -= "yy"
    println("刪除的" + map3)
    //拿取到map所有key
    println("拿取到map所有key:" + map3.keys)
    println("拿取到map所有key:" + map3.keySet)
    //獲取所有的value
    println("獲取所有的value:" + map3.values)
  }

打印的值為: 

修改的Map(lisi -> 40, zhangsan -> 50)
添加的Map(yy -> 22, lisi -> 40, zhangsan -> 50)
刪除的Map(lisi -> 40, zhangsan -> 50)
拿取到map所有key:Set(lisi, zhangsan)
拿取到map所有key:Set(lisi, zhangsan)
獲取所有的value:HashMap(40, 50)

(3)、遍歷Map

     val map3 = Map("zhangsan" -> 30, "lisi" -> 40)
    //方法一。通過遍歷key拿取到值
    for (i <- map3.keys) println(i + "->" + map3(i))
    //方法二,通過元組的方法拿取到值
    for (i <- map3) println(i._1 + "->" + i._2)
    //方法三
    for((k, v) <- map3) println(k + " -> " + v)
lisi->40
zhangsan->30
lisi->40
zhangsan->30
lisi -> 40
zhangsan -> 30

10、Set集合

  • Set是代表沒有重復(fù)元素的集合。

  • Set具備以下性質(zhì):

    • 1、元素不重復(fù)

    • 2、不保證插入順序

  • scala中的set集合也分為兩種,一種是不可變集合,另一種是可變集合。

不可變set集合 

//創(chuàng)建一個(gè)空的不可變集
val/var 變量名 = Set[類型]()

//給定元素來創(chuàng)建一個(gè)不可變集
val/var 變量名 = Set[類型](元素1, 元素2, 元素3...)
 def main(args: Array[String]): Unit = {
    val a = Set(1, 1, 2, 3, 4, 5)
    println("a的長(zhǎng)度大小"+a.size)
    for(i<-a)println(i)
    println("添加一個(gè)元素的新set:",a + 6)
    println("刪除一個(gè)元素的新set:",a -1)
    println("刪除多個(gè)元素的新set:",a -- Set(2,3) )
    println("添加多個(gè)元素的新set:",a ++ Set(6,7,8)  )
    println("多個(gè)Set集合交集的新set:",a & Set(3,4,5,6))
    println(a)
  }

打印如下:

a的長(zhǎng)度大小5
5
1
2
3
4
(添加一個(gè)元素的新set:,Set(5, 1, 6, 2, 3, 4))
(刪除一個(gè)元素的新set:,Set(5, 2, 3, 4))
(刪除多個(gè)元素的新set:,Set(5, 1, 4))
(添加多個(gè)元素的新set:,Set(5, 1, 6, 2, 7, 3, 8, 4))
(多個(gè)Set集合交集的新set:,Set(5, 3, 4))
Set(5, 1, 2, 3, 4)

注意:這里對(duì)不可變的set集合進(jìn)行添加刪除等操作,對(duì)于該集合來說是沒有發(fā)生任何變化,這里是生成了新的集合,新的集合相比于原來的集合來說發(fā)生了變化

可變Set集合

要使用可變集,必須要手動(dòng)導(dǎo)入:

import scala.collection.mutable.Set

11、列表 List

  • List是scala中最重要的、也是最常用的數(shù)據(jù)結(jié)構(gòu)。

  • List具備以下性質(zhì):

    • 1、可以保存重復(fù)的值

    • 2、有先后順序

  • 在scala中,也有兩種列表,一種是不可變列表、另一種是可變列表

  • 不可變列表就是列表的元素、長(zhǎng)度都是不可變的

  • 語法

    不可變列表

  • 使用 List(元素1, 元素2, 元素3, ...) 來創(chuàng)建一個(gè)不可變列表,語法格式
val/var 變量名 = List(元素1, 元素2, 元素3...)

//使用 Nil 創(chuàng)建一個(gè)不可變的空列表
val/var 變量名 = Nil

//使用 :: 方法創(chuàng)建一個(gè)不可變列表
val/var 變量名 = 元素1 :: 元素2 :: Nil
 def main(args: Array[String]): Unit = {
    val list1 = List(1, 2, 3, 4)
    val list2 = Nil
    val list3= 1::2::3::Nil
    println(list1(0))
    println(list3)
  }

 打印的值為

1
List(1, 2, 3)

可變列表

1、使用ListBuffer元素類型 創(chuàng)建空的可變列表,語法結(jié)構(gòu)

val/var 變量名 = ListBuffer[Int]()

2、使用ListBuffer(元素1, 元素2, 元素3...)創(chuàng)建可變列表,語法結(jié)構(gòu)

val/var 變量名 = ListBuffer(元素1,元素2,元素3...)
    val a = ListBuffer[Int]()
    val b = ListBuffer(1, 2, 3, 4)
    println(b(0))
    println("list數(shù)組首部:", b.head)
    println("獲取除了第一個(gè)元素外其他元素組成的列表", b.tail)
    b += 5
    println("添加應(yīng)元素", b)
    b ++= List(6, 7)
    println("添加一個(gè)不可變列表", b)
    b ++= ListBuffer(8, 9)
    println("添加一個(gè)可變列表", b)
    b -= 9
    println("刪除單個(gè)元素", b)
    b --= List(7,8)
    println("刪除一個(gè)不可變的列表存在的元素", b)
    b --= ListBuffer(5,6)
    println("刪除一個(gè)可變的列表存在的元素", b)
    println("toList根據(jù)可變的列表生成一個(gè)不可變列表",b.toList)
    println("toList根據(jù)可變的列表生成一個(gè)不可變列表,原列表不變",b)

    println("toArray根據(jù)可變的列表生成一個(gè)新的不可變數(shù)組",b.toArray)
    println("toArray根據(jù)可變的列表生成一個(gè)新的不可變數(shù)組,原列表不變",b)

打印如下

1
(list數(shù)組首部:,1)
(獲取除了第一個(gè)元素外其他元素組成的列表,ListBuffer(2, 3, 4))
(添加應(yīng)元素,ListBuffer(1, 2, 3, 4, 5))
(添加一個(gè)不可變列表,ListBuffer(1, 2, 3, 4, 5, 6, 7))
(添加一個(gè)可變列表,ListBuffer(1, 2, 3, 4, 5, 6, 7, 8, 9))
(刪除單個(gè)元素,ListBuffer(1, 2, 3, 4, 5, 6, 7, 8))
(刪除一個(gè)不可變的列表存在的元素,ListBuffer(1, 2, 3, 4, 5, 6))
(刪除一個(gè)可變的列表存在的元素,ListBuffer(1, 2, 3, 4))
(toList根據(jù)可變的列表生成一個(gè)不可變列表,List(1, 2, 3, 4))
(toList根據(jù)可變的列表生成一個(gè)不可變列表,原列表不變,ListBuffer(1, 2, 3, 4))
(toArray根據(jù)可變的列表生成一個(gè)新的不可變數(shù)組,[I@3567135c)
(toArray根據(jù)可變的列表生成一個(gè)新的不可變數(shù)組,原列表不變,ListBuffer(1, 2, 3, 4))

12、函數(shù)式編程

  • 我們將來使用Spark/Flink的大量業(yè)務(wù)代碼都會(huì)使用到函數(shù)式編程。

  • 下面的這些操作是學(xué)習(xí)的重點(diǎn),先來感受下如何進(jìn)行函數(shù)式編程以及它的強(qiáng)大

(1)、遍歷 - foreach

方法描述

foreach(f: (A) ? Unit): Unit
foreachAPI說明
參數(shù)f: (A) ⇒ Unit接收一個(gè)函數(shù)對(duì)象作為參數(shù) 函數(shù)的輸入?yún)?shù)為集合的元素 返回值為空
返回值Unit
  def main(args: Array[String]): Unit = {
    val list = List(1, 2, 3, 4)
    //定義一個(gè)匿名函數(shù)傳入到foreach方法中
    list.foreach((u: Int) => println(u))
    //匿名函數(shù)的輸入?yún)?shù)類型可以省略,由編譯器自動(dòng)推斷
    list.foreach(u => println(u))
    //  當(dāng)函數(shù)參數(shù),只在函數(shù)體中出現(xiàn)一次,而且函數(shù)體沒有嵌套調(diào)用時(shí),可以使用下劃線來簡(jiǎn)化函數(shù)定義
    list.foreach(println(_))
    //最簡(jiǎn)單直接
    list.foreach(println)
  }

(2)、映射 - map

  • 集合的映射操作是將來在編寫Spark/Flink用得最多的操作,是我們必須要掌握。

  • 方法描述

def map[B](f: (A) ? B): TraversableOnce[B]
  • 方法說明

ap方法API說明
泛型[B]指定map方法最終返回的集合泛型
參數(shù)f: (A) ⇒ B傳入一個(gè)函數(shù)對(duì)象作為參數(shù) 該函數(shù)接收一個(gè)類型A(要轉(zhuǎn)換的集合的元素類型) 返回值為類型B
返回值TraversableOnce[B]B類型的集合

    val list = List(1, 2, 3, 4)
    //定義一個(gè)匿名函數(shù)
    val b=list.map((i:Int)=>i*10)
    println(b)
    //省略匿名函數(shù)參數(shù)類型
    val c=list.map(i=>i*10)
    println(c)
    //最簡(jiǎn)單用下劃線的方法
    val d=  list.map(_ * 10)
    println(d)

打印結(jié)果如下

List(10, 20, 30, 40)
List(10, 20, 30, 40)
List(10, 20, 30, 40)

(3)、扁平化映射 - flatmap

  • 映射扁平化也是將來用得非常多的操作,也是必須要掌握的。

  • 方法描述

def flatMap[B](f: (A) ? GenTraversableOnce[B]): TraversableOnce[B]

方法說明  

flatmap方法API說明
泛型[B]最終要轉(zhuǎn)換的集合元素類型
參數(shù)f: (A) ⇒ GenTraversableOnce[B]傳入一個(gè)函數(shù)對(duì)象作為參數(shù) 函數(shù)的參數(shù)是集合的元素 函數(shù)的返回值是一個(gè)集合
返回值TraversableOnce[B]B類型的集合

def main(args: Array[String]): Unit = {
    val list = List("hadoop hive spark flink", "hbase spark")
    val tt = list.flatMap(x => x.split(" "));
    println(tt)
    //簡(jiǎn)寫
    val t2 = list.flatMap(_.split(" "))
    println(t2)
    //flatMap該方法其本質(zhì)是先進(jìn)行了map 然后又調(diào)用了flatten
    val t3 = list.map(_.split(" ")).flatten
    println(t3)
  }

打印結(jié)果如下

List(hadoop, hive, spark, flink, hbase, spark)
List(hadoop, hive, spark, flink, hbase, spark)
List(hadoop, hive, spark, flink, hbase, spark)

(4)、過濾 - filter

  • 過濾符合一定條件的元素

  • 方法描述

def filter(p: (A) ? Boolean): TraversableOnce[A]

 方法說明

filter方法API說明
參數(shù)p: (A) ⇒ Boolean傳入一個(gè)函數(shù)對(duì)象作為參數(shù) 函數(shù)的參數(shù)是集合中的元素 此函數(shù)返回布爾類型,滿足條件返回true, 不滿足返回false
返回值TraversableOnce[A]列表

 demo展示

def main(args: Array[String]): Unit = {
    val list = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
    ///過濾出集合中大于5的元素
    val tt=list.filter(x=>x>5)
    println(tt)
    //把集合中大于5的元素取出來乘以10生成一個(gè)新的list集合
    val t3=list.filter(x=>x>5).map(u=>u*10)
    println(t3)
  }

 打印的值為:

List(6, 7, 8, 9, 10)
List(60, 70, 80, 90, 100)

(5) 、分組 - groupBy

  • 首先集合的元素得是kv對(duì)的;

  • 如果要將數(shù)據(jù)按照某值分組來進(jìn)行統(tǒng)計(jì)分析,就需要使用到分組方法

  • groupBy表示按照函數(shù)將列表分成不同的組

  • 方法描述

def groupBy[K](f: (A) ⇒ K): Map[K, List[A]] 

  • 方法說明

groupBy方法API說明
泛型[K]分組字段的類型
參數(shù)f: (A) ⇒ K傳入一個(gè)函數(shù)對(duì)象 接收集合元素類型的參數(shù) 返回一個(gè)K類型的key,這個(gè)key會(huì)用來進(jìn)行分組,相同的key放在一組中
返回值Map[K, List[A]]返回一個(gè)映射,K為分組字段,List為這個(gè)分組字段對(duì)應(yīng)的一組數(shù)據(jù)

scala> val a = List("張三"->"男", "李四"->"女", "王五"->"男")
a: List[(String, String)] = List((張三,男), (李四,女), (王五,男))

// 按照性別分組
scala> a.groupBy(_._2)
res0: scala.collection.immutable.Map[String,List[(String, String)]] = Map(男 -> List((張三,男), (王五,男)),
女 -> List((李四,女)))

// 將分組后的映射轉(zhuǎn)換為性別/人數(shù)元組列表
scala> res0.map(x => x._1 -> x._2.size)
res3: scala.collection.immutable.Map[String,Int] = Map(男 -> 2, 女 -> 1)

//根據(jù)這個(gè)例子,思考下,作業(yè)中如何使用scala編程,實(shí)現(xiàn)詞頻統(tǒng)計(jì)?
 

//求每個(gè)省份有多少人?
val b = List("張三"->("男", "北京"), "李四"->("女", "河北"), "王五"->("男", "北京"))

scala> b.groupBy(_._2._2).map(x => (x._1, x._2.size))
res14: scala.collection.immutable.Map[String,Int] = Map(北京 -> 2, 河北 -> 1)

object yyy {
  def main(args: Array[String]): Unit = {
   val a = List("張三"->"男", "李四"->"女", "王五"->"男")
    println(a.groupBy(_._2))

    val list2 =List("a,b,c","y,c,a,e,a,c,a")
    var map=list2.flatMap(x=>x.split(",")).groupBy(x=>x).map(y=>(y._1,y._2.size));
    println(map)
    println("a的個(gè)數(shù)是:"+map("a"))
  }
}

打印的值為 

Map(男 -> List((張三,男), (王五,男)), 女 -> List((李四,女)))
Map(e -> 1, y -> 1, a -> 4, b -> 1, c -> 3)
a的個(gè)數(shù)是:4

(6)、排序 - sort

在scala集合中,可以使用以下幾種方式來進(jìn)行排序

  • sorted默認(rèn)排序

  • sortBy指定字段排序

  • sortWith自定義排序

sorted默認(rèn)排序

 def main(args: Array[String]): Unit = {
    val list = List(5, 1, 2, 4, 3)
    println(list.sorted)
  }
List(1, 2, 3, 4, 5)

sortBy指定字段排序

def sortBy[B](f: (A) ? B): List[A]
sortBy方法API說明
泛型[B]按照什么類型來進(jìn)行排序
參數(shù)f: (A) ⇒ B傳入函數(shù)對(duì)象作為參數(shù) 函數(shù)接收一個(gè)集合類型的元素為參數(shù) 返回B類型的元素進(jìn)行排序
返回值List[A]返回排序后的列表

結(jié)果如下: 

 val list2 = List("1 hadoop", "2 spark", "3 flink")
    println(list2.sortBy(x=>x.split(" ")(0)))

打印的結(jié)果如下: 

List(1 hadoop, 2 spark, 3 flink)

sortWith自定義排序  

  • 自定義排序,根據(jù)一個(gè)函數(shù)來進(jìn)行自定義排序

  • 方法描述

def sortWith(lt: (A, A) ? Boolean): List[A]
sortWith方法API說明
參數(shù)lt: (A, A) ⇒ Boolean傳入一個(gè)比較大小的函數(shù)對(duì)象作為參數(shù) 函數(shù)接收兩個(gè)集合類型的元素作為參數(shù) 返回兩個(gè)元素大小,小于返回true,大于返回false
返回值List[A]返回排序后的列表
   val list3 = List(2, 3, 1, 6, 4, 5)
    //降序
    var tt = list3.sortWith((x, y) => x > y)
    println(tt)
    //升序
    var tt2 = list3.sortWith((x, y) => x < y)
    println(tt2)
    //簡(jiǎn)寫
    var tt3 =list3.sortWith(_ > _)
    println(tt3)

 打印的結(jié)果:

List(6, 5, 4, 3, 2, 1)
List(1, 2, 3, 4, 5, 6)
List(6, 5, 4, 3, 2, 1)

(5)、聚合 - reduce

  • reduce表示將列表,傳入一個(gè)函數(shù)進(jìn)行聚合計(jì)算

  • 方法描述

def reduce[A1 >: A](op: (A1, A1) ? A1): A1
reduce方法API說明
泛型[A1 >: A](下界)A1必須是集合元素類型的子類
參數(shù)op: (A1, A1) ⇒ A1傳入函數(shù)對(duì)象,用來不斷進(jìn)行聚合操作 第一個(gè)A1類型參數(shù)為:當(dāng)前聚合后的變量 第二個(gè)A1類型參數(shù)為:當(dāng)前要進(jìn)行聚合的元素
返回值A1列表最終聚合為一個(gè)元素
def main(args: Array[String]): Unit = {
    val a = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
    //基礎(chǔ)的寫法
    var b = a.reduce((x, y) => x + y)
    println("基礎(chǔ)的寫法"+b)
    //簡(jiǎn)單的寫法
    var c = a.reduce(_ + _)
    println("簡(jiǎn)單的寫法"+c)
    //從左往右計(jì)算
    var d = a.reduceLeft(_ + _)
    println("從左往右計(jì)算"+d)
     //從右往左計(jì)算
    var f = a.reduceRight(_ + _)
    println("從右往左計(jì)算"+f)
  }
基礎(chǔ)的寫法55
簡(jiǎn)單的寫法55
從左往右計(jì)算55
從右往左計(jì)算55

(6)、折疊 - fold

fold與reduce很像,但是多了一個(gè)指定初始值參數(shù)

def fold[A1 >: A](z: A1)(op: (A1, A1) ? A1): A1
reduce方法API說明
泛型[A1 >: A](下界)A1必須是集合元素類型的子類
參數(shù)1z: A1初始值
參數(shù)2op: (A1, A1) ⇒ A1傳入函數(shù)對(duì)象,用來不斷進(jìn)行折疊操作 第一個(gè)A1類型參數(shù)為:當(dāng)前折疊后的變量 第二個(gè)A1類型參數(shù)為:當(dāng)前要進(jìn)行折疊的元素
返回值A1列表最終折疊為一個(gè)元素
def main(args: Array[String]): Unit = {
    val a = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

    var e = a.fold(0)(_ + _)
    println("簡(jiǎn)單折疊:",e)
    var g = a.fold(5)(_ + _)
    println("給定一個(gè)初始值,,折疊求和:"+g)
    var h=  a.foldLeft(10)(_ + _)
    println("從左往右折疊:",h)

  }
(簡(jiǎn)單折疊:,55)
給定一個(gè)初始值,,折疊求和:60
(從左往右折疊:,65)

13、高階函數(shù)

使用函數(shù)值作為參數(shù),或者返回值為函數(shù)值的“函數(shù)”和“方法”,均稱之為“高階函數(shù)”。

1、函數(shù)值作為參數(shù)

  def main(args: Array[String]): Unit = {
    //定義一個(gè)數(shù)組
    val array = Array(1, 2, 3, 4, 5)
    //定義一個(gè)函數(shù)
    val func = (x: Int) => x * 10
    //函數(shù)作為參數(shù)傳遞到方法中
    val tt=  array.map(func)
    println("通過map轉(zhuǎn)化的新數(shù)組:",tt)
    println("通過map轉(zhuǎn)化的新數(shù)組最大:",tt.max)
  }

打印的值為:

(通過map轉(zhuǎn)化的新數(shù)組:,[I@17550481)
(通過map轉(zhuǎn)化的新數(shù)組:,50)

2、匿名函數(shù)

一個(gè)沒有名稱的函數(shù)----匿名函數(shù)

 def main(args: Array[String]): Unit = {
    val array = Array(1, 2, 3, 4, 5)
    var a = array.map(x => x * 10)
    println(a.max)
  }

打印的值為: 

50

3、柯里化

方法可以定義多個(gè)參數(shù)列表,當(dāng)使用較少的參數(shù)列表調(diào)用多參數(shù)列表的方法時(shí),會(huì)產(chǎn)生一個(gè)新的函數(shù),該函數(shù)接收剩余的參數(shù)列表作為其參數(shù)。這被稱為柯里化。

 def main(args: Array[String]): Unit = {
    def getAddress(a: String): (String, String) => String = {
      (b: String,c: String) => a + "-" + b + "-" + c
    }
    var b=getAddress("china");
    var c=b("beijing","tianAnMen")
    println(c)
  }
china-beijing-tianAnMen

 4、閉包

函數(shù)里面引用外面類成員變量叫作閉包

  def main(args: Array[String]): Unit = {
    var factor = 1
    val f1 = (x: Int) => x * factor
    println(f1(8))
    factor=2
    println(f1(8))
  }
8
16

//定義的函數(shù)f1,它的返回值是依賴于不在函數(shù)作用域的一個(gè)變量
//后期必須要要獲取到這個(gè)變量才能執(zhí)行
//spark和flink程序的開發(fā)中大量的使用到函數(shù),函數(shù)的返回值依賴的變量可能都需要進(jìn)行大量的網(wǎng)絡(luò)傳輸獲取得到。這里就需要這些變量實(shí)現(xiàn)序列化進(jìn)行網(wǎng)絡(luò)傳輸。

 def main(args: Array[String]): Unit = {
   
    def multiply(x: Double) = (y: Double) => x * y

    //先進(jìn)行科爾化
    val doubleFunc = multiply(2)
    val tripleFunc = multiply(3)
    //    再對(duì)閉包進(jìn)行計(jì)算
    var u = doubleFunc(10)
    var u2 = tripleFunc(10)
    println(u)
    println(u2)
  }
20.0
30.0

14、scala面向?qū)ο缶幊讨?/h2>

1、類的定義

scala是支持面向?qū)ο蟮模灿蓄惡蛯?duì)象的概念。

  • 定義一個(gè)Customer類,并添加成員變量/成員方法

  • 添加一個(gè)main方法,并創(chuàng)建Customer類的對(duì)象,并給對(duì)象賦值,打印對(duì)象中的成員,調(diào)用成員方法

與java相比,他無需get set方法,就可以對(duì)變量進(jìn)行賦值封裝操作 

import java.util.Date

class Customer {
  var name: String = _
  var sex: String = _
  val registerDate: Date = new Date

  def sayHi(msg: String) = {
    println(msg)
  }
}

object Main {
  def main(args: Array[String]): Unit = {
    val customer = new Customer
    //給對(duì)象的成員變量賦值
    customer.name = "張三"
    customer.sex = "男"

    println(s"姓名: ${customer.name}, 性別:${customer.sex}, 注冊(cè)時(shí)間: ${customer.registerDate}")
    //對(duì)象調(diào)用方法
    customer.sayHi("你好!")
  }
}

 打印的結(jié)果為:

姓名: 張三, 性別:男, 注冊(cè)時(shí)間: Fri Apr 22 16:23:21 CST 2022
你好!

(1). var name:String = _,  _表示使用默認(rèn)值進(jìn)行初始化
   例如:String類型默認(rèn)值是null,Int類型默認(rèn)值是0,Boolean類型默認(rèn)值是false...
(2). val變量不能使用_來進(jìn)行初始化,因?yàn)関al是不可變的,所以必須手動(dòng)指定一個(gè)默認(rèn)值
(3). main方法必須要放在一個(gè)scala的object(單例對(duì)象)中才能執(zhí)行

2、類的構(gòu)造器

主構(gòu)造器

  • 主構(gòu)造器是指在類名的后面跟上一系列參數(shù),例如

class 類名(var/val 參數(shù)名: 類型 = 默認(rèn)值, var/val 參數(shù)名: 類型 = 默認(rèn)值){
    // 構(gòu)造代碼塊
}

輔助構(gòu)造器

  • 在類中使用this來定義,例如

    def this(參數(shù)名: 類型, 參數(shù)名: 類型) {
        ...
    }
    package com.testScala.D_lei
    
    class Student(val name: String, val age: Int) {
    
      val address: String = "beijing"
    
      // 定義一個(gè)參數(shù)的輔助構(gòu)造器
      def this(name: String) {
        // 輔助構(gòu)造器的第一行必須調(diào)用主構(gòu)造器或其他輔助構(gòu)造器或者super父類的構(gòu)造器
        this(name, 20)
      }
    
      def this(age: Int) {
        this("某某某", age)
      }
    
    }
    
    object test {
      def main(args: Array[String]): Unit = {
        val tt = new Student("張三");
        println(s"name等于:${tt.name},address:${tt.address},age:${tt.age}")
      }
    }

    15、scala面向?qū)ο缶幊讨畬?duì)象

1、scala中的object

  • scala中是沒有Java中的靜態(tài)成員的。如果將來我們需要用到static變量、static方法,就要用到scala中的單例對(duì)象object

  • 定義object

    • 定義單例對(duì)象和定義類很像,就是把class換成object

  • 演示

    • 定義一個(gè)工具類,用來格式化日期時(shí)間

object DateUtils {
//  / 在object中定義的成員變量,相當(dāng)于Java中定義一個(gè)靜態(tài)變量
  // 定義一個(gè)SimpleDateFormat日期時(shí)間格式化對(duì)象
  val simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm")

  // 構(gòu)造代碼
  println("構(gòu)造代碼")

  // 相當(dāng)于Java中定義一個(gè)靜態(tài)方法
  def format(date: Date) = simpleDateFormat.format(date)

  // main是一個(gè)靜態(tài)方法,所以必須要寫在object中
  def main(args: Array[String]): Unit = {

    println { DateUtils.format(new Date()) };
  }
}

 (1). 使用object 單例對(duì)象名定義一個(gè)單例對(duì)象,可以用object作為工具類或者存放常量
(2). 在單例對(duì)象中定義的變量,類似于Java中的static成員變量
(3). 在單例對(duì)象中定義的方法,類似于Java中的static方法
(4). object單例對(duì)象的構(gòu)造代碼可以直接寫在花括號(hào)中
(5). 調(diào)用單例對(duì)象的方法,直接使用單例對(duì)象名.方法名,訪問單例對(duì)象的成員變量也是使用單例對(duì)象名.變量名
(6). 單例對(duì)象只能有一個(gè)無參的主構(gòu)造器,不能添加其他參數(shù)

2、scala中的伴生對(duì)象

  • 在==同一個(gè)scala文件,有一個(gè)class和object具有同樣的名字==,那么就稱這個(gè)object是class的伴生對(duì)象,class是object的伴生類;

  • 伴生類和伴生對(duì)象的最大特點(diǎn)是,可以相互訪問;

package com.testScala.E_duixiang

class Dog {
  val id = 1
  private var name = "kkb"
  def printName(): Unit = {
    //在Dog類中可以訪問伴生對(duì)象Dog的私有屬性
    println(Dog.CONSTANT + name )
  }
}

object Dog{
  //伴生對(duì)象中的私有屬性
  private val CONSTANT = "汪汪汪 : "
  def main(args: Array[String]) {
    val dog = new Dog
    //訪問私有的字段name
    dog.name = "123"
    dog.printName()
  }
}
汪汪汪 : 123

(1). 伴生類和伴生對(duì)象的名字必須是一樣的
(2). 伴生類和伴生對(duì)象需要在一個(gè)scala源文件中
(3). 伴生類和伴生對(duì)象可以互相訪問private的屬性

3、scala中object的apply方法

  • ==實(shí)現(xiàn)伴生對(duì)象Array的apply方法==

  • 伴生對(duì)象的apply方法用來快速地創(chuàng)建一個(gè)伴生類的對(duì)象。

package com.testScala.E_duixiang

class Person(var name: String, var age: Int) {

  override def toString = s"Person($name, $age)"
}

object Person {
  // 實(shí)現(xiàn)apply方法
  // 返回的是伴生類的對(duì)象
  def apply(name: String, age: Int): Person = new Person(name, age)

  // apply方法支持重載
  def apply(name: String): Person = new Person(name, 20)

  def apply(age: Int): Person = new Person("某某某", age)

  def apply(): Person = new Person("某某某", 20)
}

object Main2 {
  def main(args: Array[String]): Unit = {
    val p1 = Person("張三", 20)
    val p2 = Person("李四")
    val p3 = Person(100)
    val p4 = Person()

    println(p1)
    println(p2)
    println(p3)
    println(p4)
  }
}
Person(張三, 20)
Person(李四, 20)
Person(某某某, 100)
Person(某某某, 20)

 (1). 當(dāng)遇到類名(參數(shù)1, 參數(shù)2...)會(huì)自動(dòng)調(diào)用伴生對(duì)象相應(yīng)的apply方法,在apply方法中來創(chuàng)建對(duì)象
(2). 定義apply時(shí),如果參數(shù)列表是空,也不能省略括號(hào)(),否則引用的是伴生對(duì)象

4、scala中object的main方法

  • scala和Java一樣,如果要運(yùn)行一個(gè)程序,必須有一個(gè)main方法。

  • 而在Java中main方法是靜態(tài)的,而在scala中沒有靜態(tài)方法。

object Main1{
  def main(args: Array[String]) = {
    println("hello, scala")
  }
}

16、scala面向?qū)ο缶幊讨^承

1、繼承extends

  • scala和Java一樣,使用extends關(guān)鍵字來實(shí)現(xiàn)繼承??梢栽谧宇愔卸x父類中沒有的字段和方法,或者重寫父類的方法。

  • package com.testScala.F_jicheng
    
    class Person1 {
      var name = "jianghaojie"
    
      def getName = this.name
    }
    
    class Student extends Person1
    
    object main1 {
      def main(args: Array[String]): Unit = {
        val p1 = new Person1()
        val p2 = new Student()
        p2.name = "蔣皓潔"
        println(p1.getName)
        println(p2.getName)
      }
    }
    jianghaojie
    蔣皓潔

    2、override和super

     ???如果子類要覆蓋父類中的一個(gè)非抽象方法,必須要使用override關(guān)鍵字

  • 可以使用override關(guān)鍵字來重寫一個(gè)val字段

  • 可以使用super關(guān)鍵字來訪問父類的成員

  • ==示例1:class繼承class==

class Person3 {
  val name = "super"

  def getName = name
}

class Student3 extends Person3 {
  // 重寫val字段
  override val name: String = "child"

  // 重寫getName方法
  override def getName: String = "hello, " + super.getName
}

object Main3 {
  def main(args: Array[String]): Unit = {
    val p = new Student3();
    println(p.name)
    println(p.getName)
  }
}
child
hello, child

3、isInstanceOf和asInstanceOf

  • 我們經(jīng)常要在代碼中進(jìn)行類型的判斷和類型的轉(zhuǎn)換。在Java中,我們可以使用instanceof關(guān)鍵字、以及(類型)object來實(shí)現(xiàn),在scala中如何實(shí)現(xiàn)呢?

  • scala中對(duì)象提供==isInstanceOf==和==asInstanceOf==方法。

    • isInstanceOf判斷對(duì)象是否為指定類的對(duì)象

    • asInstanceOf將對(duì)象轉(zhuǎn)換為指定類型

JavaScala
判斷對(duì)象是否是C類型obj instanceof Cobj.isInstanceof[C]
將對(duì)象強(qiáng)轉(zhuǎn)成C類型(C ) objobj.asInstanceof[C]
獲取類型為T的class對(duì)象C.classclassOf[C]
  • ==示例==

class Person4
class Student4 extends Person4

object Main4 {
  def main(args: Array[String]): Unit = {
    val s1: Person4 = new Student4

    // 判斷s1是否為Student4類型
    if(s1.isInstanceOf[Student4]) {
      // 將s1轉(zhuǎn)換為Student3類型
      val s2 =  s1.asInstanceOf[Student4]
      println(s2)
    }
  }
}
com.testScala.F_jicheng.Student4@ea4a92b

4、getClass和classOf

isInstanceOf 只能判斷出對(duì)象是否為指定類以及其子類的對(duì)象,而不能精確的判斷出,對(duì)象就是指定類的對(duì)象。如果要求精確地判斷出對(duì)象就是指定類的對(duì)象,那么就只能使用 getClass 和 classOf 。

  • 對(duì)象.getClass可以精確獲取對(duì)象的類型

  • classOf[x]可以精確獲取類型

  • 使用==操作符就可以直接比較

class Person5
class Student5 extends Person5

object Student5{
  def main(args: Array[String]) {
    val p: Person5 = new Student5
    //判斷p是否為Person5類的實(shí)例
    println(p.isInstanceOf[Person5])//true

    //判斷p的類型是否為Person5類
    println(p.getClass == classOf[Person5])//false

    //判斷p的類型是否為Student5類
    println(p.getClass == classOf[Student5])//true
  }
}

5、訪問修飾符

java中的訪問控制,同樣適用于scala,可以在成員前面添加private/protected關(guān)鍵字來控制成員的可見性。但在scala中,==沒有public關(guān)鍵字,任何沒有被標(biāo)為private或protected的成員都是公共的==。
 

==private[this]修飾符==

  • 被修飾的成員只能在當(dāng)前類中被訪問。或者可以理解為:只能通過this.來訪問(在當(dāng)前類中訪問成員會(huì)自動(dòng)添加this.)

package com.testScala.F_jicheng
class Person6 {
  // 只有在當(dāng)前對(duì)象中能夠訪問
  private[this] var name = "super"

  def getName = this.name	// 正確!

  def sayHelloTo(p: Person6) = {
    println("hello" + p.name)     // 報(bào)錯(cuò)!無法訪問
  }
}

object Person6 {
  def showName(p: Person6) = println(p.name)  // 報(bào)錯(cuò)!無法訪問
}

protected[this]修飾符==

  • ==被修飾的成員只能在當(dāng)前類和當(dāng)前類的子類中被訪問==。也可以理解為:當(dāng)前類通過this.訪問或者子類通過this.訪問

  • 示例

package com.testScala.F_jicheng

class Person7 {
  // 只有在當(dāng)前類以及繼承該類的當(dāng)前對(duì)象中能夠訪問
  protected[this] var name = "super"

  def getName = {
    // 正確!
    this.name
  }

  def sayHelloTo1(p: Person7) = {
    // 編譯錯(cuò)誤!無法訪問
//    println(p.name)
  }
}

object Person7 {
  def sayHelloTo3(p: Person7) = {
    // 編譯錯(cuò)誤!無法訪問
//    println(p.name)
  }
}

class Student7 extends Person7 {
  def showName = {
    // 正確!
    println(name)
  }

  def sayHelloTo2(p: Person7) = {
    // 編譯錯(cuò)誤!無法訪問
//    println(p.name)
  }
}
object  yy{
  def main(args: Array[String]): Unit = {
    var yu=    new Student7();
    yu.showName
//    println()
  }
}

6、調(diào)用父類的constructor

  • ==實(shí)例化子類對(duì)象,必須要調(diào)用父類的構(gòu)造器==,在scala中,只能在子類的主構(gòu)造器中調(diào)用父類的構(gòu)造器

  • 示例

 ??????

package com.testScala.F_jicheng

class Person8(var name: String){
  println("name:"+name)
}

// 直接在子類的類名后面調(diào)用父類構(gòu)造器
class Student8(name: String, var clazz: String) extends Person8(name)

object Main8 {
  def main(args: Array[String]): Unit = {
    val s1 = new Student8("張三", "三年二班")
    println(s"${s1.name} - ${s1.clazz}")
  }
}
name:張三
張三 - 三年二班

7、抽象類

  • 如果類的某個(gè)成員在當(dāng)前類中的定義是不包含完整的,它就是一個(gè)抽象類

  • 不完整定義有兩種情況:

    • 1.方法沒有方法體

    • 2.變量沒有初始化

  • 沒有方法體的方法稱為抽象方法,沒有初始化的變量稱為抽象字段。定義抽象類和Java一樣,在類前面加上abstract關(guān)鍵字就可以了

package com.testScala.F_jicheng

abstract class Person9(val name: String) {
  //抽象方法
  def sayHello: String
  def sayBye: String
  //抽象字段
  val address: String
}
class Student9(name: String) extends Person9(name){
  //重寫抽象方法或字段,def前不必加override關(guān)鍵字
  def sayHello: String = "Hello," + name
  def sayBye: String ="Bye," + name
  //重寫抽象字段
   val address: String = "beijing "
}
object Main9{
  def main(args: Array[String]) {
    val s = new Student9("tom")
    println(s.sayHello)
    println(s.sayBye)
    println(s.address)
  }
}
Hello,tom
Bye,tom
beijing 

17、scala面向?qū)ο缶幊讨畉rait特質(zhì)

  • 特質(zhì)是scala中代碼復(fù)用的基礎(chǔ)單元

  • 它可以將方法和字段定義封裝起來,然后添加到類中

  • 與類繼承不一樣的是,類繼承要求每個(gè)類都只能繼承一個(gè)超類,而一個(gè)類可以添加任意數(shù)量的特質(zhì)。

  • 特質(zhì)的定義和抽象類的定義很像,但它是使用trait關(guān)鍵字

1、作為接口使用

  • 使用extends來繼承trait(scala不論是類還是特質(zhì),都是使用extends關(guān)鍵字)

  • 如果要繼承多個(gè)trait,則使用with關(guān)鍵字

==示例一:繼承單個(gè)trait==  

trait Logger1 {
  // 抽象方法
  def log(msg: String)
}

class ConsoleLogger1 extends Logger1 {
  override def log(msg: String): Unit = println(msg)
}

object LoggerTrait1 {
  def main(args: Array[String]): Unit = {
    val logger = new ConsoleLogger1
    logger.log("控制臺(tái)日志: 這是一條Log")
  }
}
控制臺(tái)日志: 這是一條Log

==示例二:繼承多個(gè)trait==

trait Logger2 {
  // 抽象方法
  def log(msg: String)
}

trait MessageSender {
  def send(msg: String)
}

class ConsoleLogger2 extends Logger2 with MessageSender {

  override def log(msg: String): Unit = println(msg)

  override def send(msg: String): Unit = println(s"發(fā)送消息:${msg}")
}

object LoggerTrait2 {
  def main(args: Array[String]): Unit = {
    val logger = new ConsoleLogger2
    logger.log("控制臺(tái)日志: 這是一條Log")
    logger.send("你好!")
  }
}
控制臺(tái)日志: 這是一條Log
發(fā)送消息:你好!

2、定義具體的方法

  • 和類一樣,trait中還可以定義具體的方法。

  • ==示例==

package com.testScala.G_trait

trait LoggerDetail {
  // 在trait中定義具體方法
  def log(msg: String) = println(msg)
}

class PersonService extends LoggerDetail {
  def add() = log("添加用戶")
}

object MethodInTrait {
  def main(args: Array[String]): Unit = {
    val personService = new PersonService
    personService.add()
  }
}
添加用戶

3、定義具體方法和抽象方法

  • 在trait中,可以混合使用具體方法和抽象方法

  • 使用具體方法依賴于抽象方法,而抽象方法可以放到繼承trait的子類中實(shí)現(xiàn),這種設(shè)計(jì)方式也稱為模板模式

==示例==

package com.testScala.G_trait

trait Logger3 {
  // 抽象方法
  def log(msg: String)
  // 具體方法(該方法依賴于抽象方法log
  def info(msg: String) = log("INFO:" + msg)
  def warn(msg: String) = log("WARN:" + msg)
  def error(msg: String) = log("ERROR:" + msg)
}

class ConsoleLogger3 extends Logger3 {
  override def log(msg: String): Unit = println(msg)
}

object LoggerTrait3 {
  def main(args: Array[String]): Unit = {
    val logger3 = new ConsoleLogger3

    logger3.log("這是一條日志信息")
    logger3.info("這是一條普通信息")
    logger3.warn("這是一條警告信息")
    logger3.error("這是一條錯(cuò)誤信息")
  }
}
這是一條日志信息
INFO:這是一條普通信息
WARN:這是一條警告信息
ERROR:這是一條錯(cuò)誤信息

4、定義具體字段和抽象字段

  • 在trait中可以定義具體字段和抽象字段

  • 繼承trait的子類自動(dòng)擁有trait中定義的字段

  • 字段直接被添加到子類中

package com.testScala.G_trait

import java.text.SimpleDateFormat
import java.util.Date

trait LoggerEx {
  // 具體字段
  val sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm")
  val INFO = "信息:" + sdf.format(new Date)
  // 抽象字段
  val TYPE: String

  // 抽象方法
  def log(msg: String)
}

class ConsoleLoggerEx extends LoggerEx {
  // 實(shí)現(xiàn)抽象字段
  override val TYPE: String = "控制臺(tái)"
  // 實(shí)現(xiàn)抽象方法
  override def log(msg: String): Unit = print(s"$TYPE$INFO $msg")
}

object FieldInTrait {
  def main(args: Array[String]): Unit = {
    val logger = new ConsoleLoggerEx

    logger.log("這是一條消息")
  }
}
控制臺(tái)信息:2022-04-24 15:05 這是一條消息

5、實(shí)例對(duì)象混入trait

  • trait還可以混入到實(shí)例對(duì)象中,給對(duì)象實(shí)例添加額外的行為

  • 只有混入了trait的對(duì)象才具有trait中的方法,其他的類對(duì)象不具有trait中的行為

  • 使用with將trait混入到實(shí)例對(duì)象中

  • ==示例==

package com.testScala.G_trait

trait LoggerMix {
  def log(msg: String) = println(msg)
}

class UserService

object FixedInClass {
  def main(args: Array[String]): Unit = {
    // 使用with關(guān)鍵字直接將特質(zhì)混入到對(duì)象中
    val userService = new UserService with LoggerMix
    userService.log("你好")
  }
}
你好

18、模式匹配和樣例類

  • scala有一個(gè)十分強(qiáng)大的模式匹配機(jī)制,可以應(yīng)用到很多場(chǎng)合。

    • switch語句

    • 類型查詢

    • 以及快速獲取數(shù)據(jù)

  • 并且scala還提供了樣例類,對(duì)模式匹配進(jìn)行了優(yōu)化,可以快速進(jìn)行匹配。

1、匹配字符串

import scala.util.Random


//todo:匹配字符串
object CaseDemo01 extends App{
  //定義一個(gè)數(shù)組
  val arr = Array("hadoop", "zookeeper", "spark", "storm")

  //隨機(jī)取數(shù)組中的一位,使用Random.nextInt
  val name = arr(Random.nextInt(arr.length))
  println(name)

  name match {
    case "hadoop"     => println("大數(shù)據(jù)分布式存儲(chǔ)和計(jì)算框架...")
    case "zookeeper"  => println("大數(shù)據(jù)分布式協(xié)調(diào)服務(wù)框架...")
    case "spark"      => println("大數(shù)據(jù)分布式內(nèi)存計(jì)算框架...")
    //表示以上情況都不滿足才會(huì)走最后一個(gè)
    case _            => println("我不認(rèn)識(shí)你")
  }
}
hadoop
大數(shù)據(jù)分布式存儲(chǔ)和計(jì)算框架...

2、匹配類型

//todo:匹配類型
object CaseDemo02 extends App{
  //定義一個(gè)數(shù)組
  val arr = Array("hello", 1, -2.0, CaseDemo02)

  //隨機(jī)獲取數(shù)組中的元素
  val value = arr(Random.nextInt(arr.length))
  println(value)

  value match {
    case x: Int                => println("Int=>"+x)
    case y: Double if(y >= 0)    => println("Double=>"+y)
    case z: String             => println("String=>"+z)
    case _                     => throw new Exception("not match exception")
  }
}
hello
String=>hello

3、匹配數(shù)組

package com.testScala.H_pipei

//匹配數(shù)組
object CaseDemo03 extends App{

  //匹配數(shù)組
  val arr = Array(1, 3, 5)
  arr match {
    case Array(1, x, y) => println(x + "---" + y)
    case Array(1, _*)   => println("1...")
    case Array(0)       => println("only 0")
    case _              => println("something else")

  }
}

1...

4、匹配集合

//匹配集合
object CaseDemo04 extends App{

  val list = List(0, 3, 6)
  list match {
    case 0::Nil        => println("only 0")
    case 0::tail       => println("0....")
    case x::y::z::Nil  => println(s"x:$x y:$y z:$z")
    case _             => println("something else")
  }
}
0....

5、匹配元組

package com.testScala.H_pipei

//匹配元組
object CaseDemo05 extends App{

  val tuple = (1, 3, 5)
  tuple match {
    case (1, x, y)    => println(s"1,$x,$y")
    case (2, x, y)    => println(s"$x,$y")
    case _            => println("others...")
  }
}
1,3,5

6、樣例類

  • 樣例類是一種特殊類,它可以用來快速定義一個(gè)用于保存數(shù)據(jù)的類(類似于Java POJO類),==而且它會(huì)自動(dòng)生成apply方法,允許我們快速地創(chuàng)建樣例類實(shí)例對(duì)象==。后面在并發(fā)編程和spark、flink這些框架也都會(huì)經(jīng)常使用它。

  • 定義樣例類

  • 語法結(jié)構(gòu)

case class 樣例類名(成員變量名1: 類型1, 成員變量名2: 類型2 ...)

package com.testScala.H_pipei

// 定義一個(gè)樣例類
// 樣例類有兩個(gè)成員name、age
case class CasePerson(name: String, age: Int)

// 使用var指定成員變量是可變的
case class CaseStudent(var name: String, var age: Int)

object CaseClassDemo {
  def main(args: Array[String]): Unit = {
    // 1. 使用new創(chuàng)建實(shí)例
    val zhagnsan = new CasePerson("張三", 20)
    println(zhagnsan)

    // 2. 使用類名直接創(chuàng)建實(shí)例
    val lisi = CasePerson("李四", 21)
    println(lisi)

    // 3. 樣例類默認(rèn)的成員變量都是val的,除非手動(dòng)指定變量為var類型
    //lisi.age = 22  // 編譯錯(cuò)誤!age默認(rèn)為val類型

    val xiaohong = CaseStudent("小紅", 23)
    xiaohong.age = 24
    println(xiaohong)
  }
}
CasePerson(張三,20)
CasePerson(李四,21)
CaseStudent(小紅,24)

樣例對(duì)象

  • 使用case object可以創(chuàng)建樣例對(duì)象。樣例對(duì)象是單例的,而且它沒有主構(gòu)造器。樣例對(duì)象是可序列化的。格式:

case object 樣例對(duì)象名

case class SendMessage(text: String)

// 消息如果沒有任何參數(shù),就可以定義為樣例對(duì)象
case object startTask
case object PauseTask
case object StopTask

case class SubmitTask(id: String, name: String)
case class HeartBeat(time: Long)
case object CheckTimeOutTask

object CaseDemo06 extends App{
  val arr = Array(CheckTimeOutTask,
    HeartBeat(10000),
    SubmitTask("0001", "task-0001"))

  arr(Random.nextInt(arr.length)) match {

    case SubmitTask(id, name) => println(s"id=$id, name=$name")
    case HeartBeat(time)      => println(s"time=$time")
    case CheckTimeOutTask     => println("檢查超時(shí)")
  }
}
檢查超時(shí)

7、Option類型

  • 在Scala中Option類型用樣例類來表示可能存在或也可能不存在的值

  • Option類型有2個(gè)子類

  • 一個(gè)是Some

    • Some包裝了某個(gè)值

  • 一個(gè)是None

    • None表示沒有值

object TestOption {
  def main(args: Array[String]) {
    val map = Map("a" -> 1, "b" -> 2)

    val value: Option[Int] = map.get("b")
    println(value)
    val v1 = value match {
      case Some(i) => i
      case None => 0
    }
    println(v1)

    //更好的方式
    val v2 = map.getOrElse("c", 0)
    println(v2)
  }
}
Some(2)
2
0

8、偏函數(shù)

  • 被包在花括號(hào)內(nèi)==沒有match的一組case語句==是一個(gè)偏函數(shù)

  • 它是PartialFunction[A, B]的一個(gè)實(shí)例,

    • A代表輸入?yún)?shù)類型

    • B代表返回結(jié)果類型

    • 可以理解為:偏函數(shù)是一個(gè)參數(shù)和一個(gè)返回值的函數(shù)。

  • ==示例==

object TestPartialFunction {
  // func1是一個(gè)輸入?yún)?shù)為Int類型,返回值為String類型的偏函數(shù)
  val func1: PartialFunction[Int, String] = {
    case 1 => "一個(gè)"
    case 2 => "二個(gè)"
    case 3 => "三個(gè)"
    case _ => "其他"
  }

  def main(args: Array[String]): Unit = {
    println(func1(1))

    val list = List(1, 2, 3, 4, 5, 6)

    //使用偏函數(shù)操作
    val result = list.filter{
      case x if x >3 => true
      case _ => false
    }
    println(result)
  }

19、異常處理

 ??????

def main(args: Array[String]): Unit = {
   val i = 10 / 0
    
    println("你好!")
  }

Exception in thread "main" java.lang.ArithmeticException: / by zero
	at ForDemo$.main(ForDemo.scala:3)
	at ForDemo.main(ForDemo.scala)

執(zhí)行程序,可以看到scala拋出了異常,而且沒有打印出來"你好"。說明程序出現(xiàn)錯(cuò)誤后就終止了。那怎么解決該問題呢?

1、 捕獲異常

  • 在scala中,可以使用異常處理來解決這個(gè)問題。

    • 在Scala里,借用了==模式匹配的思想來做異常的匹配==

    • 以下為scala中try...catch異常處理的語法格式:

try {
    // 代碼
}
catch {
    case ex: 異常類型1 => // 代碼
    case ex: 異常類型2 => // 代碼
}
finally {
    // 代碼

  • try中的代碼是我們編寫的業(yè)務(wù)處理代碼

  • 在catch中表示當(dāng)出現(xiàn)某個(gè)異常時(shí),需要執(zhí)行的代碼

  • 在finally中,是不管是否出現(xiàn)異常都會(huì)執(zhí)行的代碼

try {
    val i = 10 / 0

} catch {
    case ex: Exception => println(ex.getMessage)
} finally {
    println("我始終都會(huì)執(zhí)行!")
}

2、拋出異常

  • 我們也可以在一個(gè)方法中,拋出異常。語法格式和Java類似,使用throw new Exception...

  • ==示例==

  def main(args: Array[String]): Unit = {
    throw new Exception("這是一個(gè)異常")
  }

Exception in thread "main" java.lang.Exception: 這是一個(gè)異常
	at ForDemo$.main(ForDemo.scala:3)
	at ForDemo.main(ForDemo.scala)

20、提取器(Extractor)

  • =提取器是從傳遞給它的對(duì)象中提取出構(gòu)造該對(duì)象的參數(shù)==。(回想樣例類進(jìn)行模式匹配提取參數(shù))

  • scala 提取器是一個(gè)帶有unapply方法的對(duì)象。

    • ==unapply方法算是apply方法的反向操作==

    • unapply接受一個(gè)對(duì)象,然后從對(duì)象中提取值,提取的值通常是用來構(gòu)造該對(duì)象的值。

package com.testScala.I_Extractor

class Student {
  var name: String = _   // 姓名
  var age: Int = _       // 年齡

  // 實(shí)現(xiàn)一個(gè)輔助構(gòu)造器
  def this(name: String, age: Int) = {
    this()

    this.name = name
    this.age = age
  }
}

object Student {
  def apply(name: String, age: Int): Student = new Student(name, age)

  // 實(shí)現(xiàn)一個(gè)解構(gòu)器
  def unapply(arg: Student): Option[(String, Int)] = Some(arg.name, arg.age)
}

object extractor_DEMO {
  def main(args: Array[String]): Unit = {
    val zhangsan = Student("張三", 20)

    zhangsan match {
      case Student(name, age) => println(s"姓名:$name 年齡:$age")
      case _ => println("未匹配")
    }
  }
}
姓名:張三 年齡:20

21、泛型

    scala和Java一樣,類和特質(zhì)、方法都可以支持泛型。我們?cè)趯W(xué)習(xí)集合的時(shí)候,一般都會(huì)涉及到泛型。

在scala中,使用方括號(hào)來定義==類型參數(shù)==。

1、定義一個(gè)泛型方法

object learn01 {
  def getMiddle[A](arr: Array[A]) = arr(arr.length / 2)

  def main(args: Array[String]): Unit = {
    val arr1 = Array(1, 2, 3, 4, 5)
    val arr2 = Array("a", "b", "c", "d", "f")

    println(getMiddle[Int](arr1))
    println(getMiddle[String](arr2))

    // 簡(jiǎn)寫方式,scala自動(dòng)進(jìn)行類型推斷
    println(getMiddle(arr1))
    println(getMiddle(arr2))
  }
}

2、定義一個(gè)泛型類

定義一個(gè)Pair類包含2個(gè)類型不固定的泛型

package com.testScala.J_fanxing


  // 類名后面的方括號(hào),就表示這個(gè)類可以使用兩個(gè)類型、分別是T和S
  // 這個(gè)名字可以任意取
  class Pair[T, S](val first: T, val second: S)

  case class People(var name: String, val age: Int)

  object Pair {
    def main(args: Array[String]): Unit = {

      val p1 = new Pair[String, Int]("張三", 10)
      println(p1.first)
      val p2 = new Pair[String, String]("張三", "1988-02-19")
      println(p2.first)
      val p3 = new Pair[People, People](People("張三", 20), People("李四", 30))
      println(p3.first.age)
    }
  }
張三
張三
20

22、上下界

  • ==在指定泛型類型時(shí),有時(shí)需要界定泛型類型的范圍,而不是接收任意類型==。比如,要求某個(gè)泛型類型,必須是某個(gè)類的子類,這樣在程序中就可以放心的調(diào)用父類的方法,程序才能正常的使用與運(yùn)行.

  • scala的上下邊界特性允許泛型類型是某個(gè)類的子類,或者是某個(gè)類的父類

    • 1、 ==U >: T==

      這是類型==下界==的定義,也就是U必須是類型T的父類或者是T類型本身。

    • 2、 ==U <: T==

      這是類型==上界==的定義,也就是U必須是類型T的子類或者是T類型本身。

  • ==示例一==

package com.testScala.J_fanxing

// 類名后面的指定泛型的范圍 ----上界
class Pair1[T &lt;: Person, S &lt;: Person](val first: T, val second: S) {
  def chat(msg: String) = println(s"${first.name}對(duì)${second.name}說: $msg")
}

class Person(var name: String, val age: Int)

object Pair1 {
  def main(args: Array[String]): Unit = {

    val p3 = new Pair1[Person, Person](new Person("張三", 20), new Person("李四", 30))
    p3.chat("你好啊!")
  }
}
張三對(duì)李四說: 你好??!

==示例二==

class Pair22[T &lt;: Person, S &gt;: Policeman &lt;: Person](val first: T, val second: S) {
  def chat(msg: String) = println(s"${first.name}對(duì)${second.name}說: $msg")
}

class Person(var name: String, val age: Int)
class Policeman(name: String, age: Int) extends Person(name, age)
class Superman(name: String) extends Policeman(name, -1)

object Pai {
  def main(args: Array[String]): Unit = {
    // 編譯錯(cuò)誤:第二個(gè)類型參數(shù)必須是Person的子類(包括本身)、Policeman的父類(包括本身)
    val p3 = new Pair22[Person, Policeman](new Person("張三", 20), new Policeman("李四",20))
    p3.chat("你好啊!")
  }
}
張三對(duì)李四說: 你好啊!

23、協(xié)變、逆變、非變

  • 來一個(gè)類型轉(zhuǎn)換的問題

class Pair[T](a: T)

object Pair {
  def main(args: Array[String]): Unit = {
    val p1 = new Pair("hello")
    // 編譯報(bào)錯(cuò),無法將p1轉(zhuǎn)換為p2
    val p2: Pair[AnyRef] = p1

    println(p2)
  }
}

==協(xié)變==

class Pair[+T],這種情況是協(xié)變。類型B是A的子類型,Pair[B]可以認(rèn)為是Pair[A]的子類型。這種情況,參數(shù)化類型的方向和類型的方向是一致的。

==逆變==

class Pair[-T],這種情況是逆變。類型B是A的子類型,Pair[A]反過來可以認(rèn)為是Pair[B]的子類型。這種情況,參數(shù)化類型的方向和類型的方向是相反的。 

==非變==

class Pair[T]{},這種情況就是非變(默認(rèn)),類型B是A的子類型,Pair[A]和Pair[B]沒有任何從屬關(guān)系,這種情況和Java是一樣的。 

package com.testScala.K_xieBian

class Super
class Sub extends Super

//非變
class Temp1[A](title: String)
//協(xié)變
class Temp2[+A](title: String)
//逆變
class Temp3[-A](title: String)

object Covariance_demo {
  def main(args: Array[String]): Unit = {
    val a = new Sub()
    // 沒有問題,Sub是Super的子類
    val b: Super = a

    // 非變
    val t1: Temp1[Sub] = new Temp1[Sub]("測(cè)試")
    // 報(bào)錯(cuò)!默認(rèn)不允許轉(zhuǎn)換
    // val t2: Temp1[Super] = t1

    // 協(xié)變
    val t3: Temp2[Sub] = new Temp2[Sub]("測(cè)試")
    val t4: Temp2[Super] = t3

    // 逆變
    val t5: Temp3[Super] = new Temp3[Super]("測(cè)試")
    val t6: Temp3[Sub] = t5
  }
}

 ==總結(jié)==

C[+T]:如果A是B的子類,那么C[A]是C[B]的子類。
C[-T]:如果A是B的子類,那么C[B]是C[A]的子類。
C[T]: 無論A和B是什么關(guān)系,C[A]和C[B]沒有從屬關(guān)系。

24、隱式轉(zhuǎn)換和隱式參數(shù)

1 隱式轉(zhuǎn)換

  • Scala提供的隱式轉(zhuǎn)換和隱式參數(shù)功能,是非常有特色的功能。是Java等編程語言所沒有的功能。

  • 它可以允許你手動(dòng)指定,將某種類型的對(duì)象轉(zhuǎn)換成其他類型的對(duì)象或者是給一個(gè)類增加方法。通過這些功能,可以實(shí)現(xiàn)非常強(qiáng)大、特殊的功能。

  • 隱式轉(zhuǎn)換其核心就是定義一個(gè)使用 ==implicit== 關(guān)鍵字修飾的方法 實(shí)現(xiàn)把一個(gè)原始類轉(zhuǎn)換成目標(biāo)類,進(jìn)而可以調(diào)用目標(biāo)類中的方法

.2 隱式參數(shù)

  • 所謂的隱式參數(shù),指的是在函數(shù)或者方法中,定義一個(gè)用implicit修飾的參數(shù),此時(shí)Scala會(huì)嘗試找到一個(gè)指定類型的用implicit修飾的值,即==隱式值==,并注入?yún)?shù)。

  • ==所有的隱式轉(zhuǎn)換和隱式參數(shù)必須定義在一個(gè)object中==

  • package com.kaikeba.implic_demo
    
    //todo:隱式轉(zhuǎn)換案例二:超人變身
    class Man(val name: String)
    
    class SuperMan(val name: String) {
      def heat = print("超人打怪獸")
    }
    
    object SuperMan{
      //隱式轉(zhuǎn)換方法
      implicit def man2SuperMan(man: Man) = new SuperMan(man.name)
    
      def main(args: Array[String]) {
          val hero = new Man("hero")
          //Man具備了SuperMan的方法
          hero.heat
      }
    }

到此這篇關(guān)于Scala基礎(chǔ)語法總結(jié)的文章就介紹到這了,更多相關(guān)Scala基礎(chǔ)語法詳解內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Windows7下安裝Scala 2.9.2教程

    Windows7下安裝Scala 2.9.2教程

    這篇文章主要介紹了Windows7下安裝Scala 2.9.2教程,本文給出了Scala的安裝步驟以及在Eclipse IDE安裝Scala的步驟,需要的朋友可以參考下
    2015-03-03
  • Scala實(shí)現(xiàn)二分查找的代碼實(shí)例

    Scala實(shí)現(xiàn)二分查找的代碼實(shí)例

    這篇文章主要介紹了Scala實(shí)現(xiàn)二分查找的代碼實(shí)例,找到數(shù)組的中間值,和需要查找的值進(jìn)行對(duì)比:如果中間值等于查找值,直接返回中間值下標(biāo);如果中間值大于查找值,則遞歸向左邊查找;如果中間值小于查找值,則遞歸向右邊查找,直到找完所有的元素,需要的朋友可以參考下
    2023-11-11
  • Scala基礎(chǔ)簡(jiǎn)介及代碼示例

    Scala基礎(chǔ)簡(jiǎn)介及代碼示例

    這篇文章主要介紹了Scala基礎(chǔ)簡(jiǎn)介及代碼示例,小編覺得挺不錯(cuò)的,這里給大家分享下,供需要的朋友參考。
    2017-10-10
  • Scala基礎(chǔ)語法總結(jié)

    Scala基礎(chǔ)語法總結(jié)

    這篇文章主要介紹了Scala基礎(chǔ)語法總結(jié),需要的朋友可以參考下
    2023-10-10
  • 淺談Scala的Class、Object和Apply()方法

    淺談Scala的Class、Object和Apply()方法

    下面小編就為大家?guī)硪黄獪\談Scala的Class、Object和Apply()方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-05-05
  • Scala排序算法之歸并排序解析

    Scala排序算法之歸并排序解析

    這篇文章主要介紹了Java排序算法之歸并排序解析,簡(jiǎn)介:歸并排序是一種經(jīng)典的排序算法,它采用分治的思想,將待排序的數(shù)組不斷地分割成小的子數(shù)組,然后再將這些子數(shù)組合并成有序的數(shù)組,需要的朋友可以參考下
    2023-10-10
  • Scala安裝及環(huán)境圖文配置教程

    Scala安裝及環(huán)境圖文配置教程

    這篇文章主要為大家詳細(xì)介紹了Scala安裝及環(huán)境圖文配置教程,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-03-03
  • 利用Gradle如何構(gòu)建scala多模塊工程的步驟詳解

    利用Gradle如何構(gòu)建scala多模塊工程的步驟詳解

    這篇文章主要給大家介紹了關(guān)于如何利用Gradle構(gòu)建scala多模塊工程的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2018-04-04

最新評(píng)論