1. 程式人生 > 其它 >Scala學習歷險記(第一天)

Scala學習歷險記(第一天)

Scala學習筆記(一)

前言:由於最近要整大資料相關的東西,所以java開發的我很苦逼的來學習Scala了,為接下來的工作做知識儲備,今天是2021年8月19號,是我接觸scala語言的第一天,因此整理一下一天所得,可能比較簡單基礎,但作為第一次接觸而言,算是不少收穫了,之後也會在學習的過程中邊整理邊總結。下面這段話是百度上看到的Scala 是一門多正規化(multi-paradigm)的程式語言,設計初衷是要整合面向物件程式設計和函數語言程式設計的各種特性。Scala 執行在 Java 虛擬機器上,併兼容現有的 Java 程式。Scala 原始碼被編譯成 Java 位元組碼,所以它可以運行於 JVM 之上,並可以呼叫現有的 Java 類庫。

可見scala語言和java的密不可分,接下來的學習也會結合它倆的特性來進行總結。

安裝及配置Scala的環境

  • 首先自己電腦上先擁有Java 8或者11的執行環境,具體可以參考https://www.runoob.com/java/java-environment-setup.html這一塊不再贅述。
  • 下載scala的安裝包,在http://www.scala-lang.org/downloads上,這裡我選擇的是scala2版本,比較穩定,我下載的是scala-2.13.6.msi。
  • 下載下來之後直接雙擊安裝scala,注意選擇安裝目錄時資料夾不要有空格,我第一次安裝在了Program Files (x86),結果一直提示我'scala' 不是內部或外部命令,也不是可執行的程式 或批處理檔案。
    ,更換目錄後就好了。
  • 配置環境變數,這裡的配置和java及其相似,只不過要新建一個變數名為SCALA_HOME,變數值為scala安裝路徑的系統環境變數(java建的是JAVA_HOME)。然後在Path內新增上"%SCALA_HOME%\bin"即可
  • 因為我是用的idea開發,因為首先我先去了IDEA中的file->setting->Plugins中搜索了Scala外掛,下載下來安裝後重啟idea
  • 然後新建專案和java的步驟如出一轍,只不過選擇型別時不要選擇java,要選擇Scala,一路next,最後剛建出來時要等一會兒,因為它這裡需要下載相關的依賴jar一類的,我大約等了十幾分鍾吧。等到載入完,就可以新建scala檔案,進行愉快的開發了。

Scala的基本操作用法

scala和java很大的區別在於它每一行語句結束後,可以不用寫;,但是在一行裡想編寫多個不同的語句,就需要用分隔開,scala和java很多的關鍵字都是一樣的,只不過是使用的語法上有所差異,接下來便通過我寫的一些demo來感受scala的用法吧,就不再囉裡囉嗦的講學術了。我也是初學者,有不對的多多指教。

scala的常規使用

/**
 * scala基礎
 * @author: zae
 * @date: 2021/8/19
 * @time: 11:09
 */
object FirstScala {
  /**
   *
   * @param args
   */
  def main(args: Array[String]) {
    // 第一個scala方法=輸出 Hello World
    println("Hello, world!")

    // 定義變數: var關鍵字
    var name : String = "Zae";println("我的名字叫:"+name);name = "aaa"
    var age : Int = 25; println("我的年齡是"+age);

    // 定義常量: val關鍵字,不能修改
    val address : String  = "北京";

    // 支援多個變數宣告
    var num1,num2 = 100

    // 元祖
    var po:(Int,String) = (40,"four"); println(po)

    // for迴圈的使用
    println("=========for迴圈的使用=============")
    var i = 0;
    for (i <- 10 to 20){
      // 這裡值的是從10迴圈到20
      println("for in to:"+i)
    }
    for(i <- 10 until 20){
      // 這裡指的是從10迴圈到19,就是不包含最後的那個20了
      println("for in until"+i)
    }
    var j = 0;
    for(i <- 1 to 4;j <- 1 to 3){
      // 羅列出了所有i和j組合的可能性,類似於java中的雙重for迴圈
      println("i="+i+"||j="+j);
    }
    // for迴圈結合集合使用
    val newList = List(2,3,4,5,6,7,8)
    for(i <- newList){
      println("集合for使用:"+i)
    }

    // for+if過濾
    for(i <- newList
        if i>=3;if i<=7){
      // 意思是遍歷newList,並篩選出大於等於3和小於等於7的元素
      println("過濾後的結果為:"+i)
    }

    // for使用yield,將過濾結果進行儲存
    val result = for{i<-newList
        if i>=4;if i<=6}yield i
    // 輸出返回值
    for(i <- result){
      println("收集的結果為"+i)
    }

    println("============while和do while的使用")
    var a = 0
    while (a<=5){
      a = a+1
      println("while的第"+a+"次迴圈")
    }
    do{
      println(" do while的第"+a+"次迴圈")
      a=a+1
    }while(a<=10)
  }

scala關於訪問修飾符

/**
 * 關於訪問修飾符
 * @author: zae
 * @date: 2021/8/19
 * @time: 11:41
 */
class TwoScala {
  // private訪問修飾符,成員物件定義的類以及其內部類可見
  class InnerOne{
    private def f(){println("f")}
    class InnerMost{
      f() 
    }
  }

  // protected訪問修飾符 只允許子類訪問
  protected def testM(){println("protected")}
  class TwoScalaSmall extends TwoScala{
    testM()
  }

  // public都可以訪問,預設情況就是public
  class InnerTwo{
    def testPub(){println("public")}
  }
  class  InnerThree{
    (new InnerTwo).testPub()
  }

}

Scala函式和方法

Scala函式這一塊看起來要比java精彩一些,種類特別多,除了基礎常見的定義函式加呼叫,還有10種比較特殊的,分別是函式傳名呼叫(Call-by-Name)函式 - 可變引數預設引數值內嵌函式偏應用函式指定函式引數名遞迴函式高階函式匿名函式函式柯里化(Function Currying)。下面將通過我的demo演示各種函式的用法,有些解釋直接寫在註釋中了。

import java.util.Date

/**
 * scala函式和方法
 * @author: zae
 * @date: 2021/8/19
 * @time: 14:44
 */
object SecondScala {

  def main(args: Array[String]){
    // 呼叫sum方法
    println("1+2="+sum(1,2))
    // 呼叫無參無返回方法
    outWord()
    // 傳名呼叫使用
    dealTime(getNowTime())
    // 呼叫可變引數函式
    useParams("無盡","名刀","末世")
    // 呼叫含預設引數的方法-不傳參
    println("不傳參:a+b="+defaultParam())
    // 呼叫含預設引數的方法-傳參
    println("傳參:a+b="+defaultParam(100,200))
    // 呼叫內嵌函式
    println("內嵌函式結果為:"+innerFun(4))
    // 呼叫偏應用函式
    appFunc();
    // 指定引數名進行呼叫
    nameFun(b = 10,a = 20)
    // 呼叫遞迴函式
    println("5的階乘結果為:"+factFun(5))
    // 高階函式
    println(apply(layout,10))
    // 呼叫匿名函式
    println("呼叫匿名函式的結果為:"+multFun(2,3))
    // 呼叫柯里化後的函式
    println("函式柯里化:"+addFunKe(5)(6))
    // 呼叫閉包類的函式
    println("閉包:"+multOneFun(10))

  }

  // 定義一個方法計算a+b
  def sum(a:Int,b:Int) : Int = {
    var num : Int = 0
    num = a+b
    return num
  }
  // 定義一個無返回值的方法
  def outWord(): Unit={
    println("我是一個無參無返回值的方法")
  }

  def getNowTime() = {
    println("獲取時間,單位為納秒")
    System.nanoTime()
  }

  // 定義傳名方法
  def dealTime(t: =>Long) = {
    println("在dealTime方法內部")
    println("當前時間:"+t)
    t
  }

  // 定義可變引數函式
  def useParams(args:String*) ={
    var i : Int = 0
    for(arg <- args){
      println("args["+i+"]="+arg)
      i = i+1
    }
  }

  // 定義含預設引數的函式
  def defaultParam(a:Int = 10,b:Int = 20):Int = {
    var num : Int = 0
    num = a+b
    num
  }

  // 內嵌函式
  def innerFun(a:Int):Int={
    def fact(i:Int,defaultNum:Int):Int = {
      if(i<=1)
        defaultNum
      else
        fact(i-1,i*defaultNum)
    }
    fact(a,1)
  }

  // 偏應用函式
  def appFunc() = {
    println("===開啟偏應用函式的呼叫模式===")
    val date = new Date
    val logWithDate = log(date,_:String)
    logWithDate("message1")
    logWithDate("message2")
    logWithDate("message3")
  }
  def log(date:Date,message:String) = {
    println(date+"===="+message)
  }

  // 指定函式引數名
  def nameFun(a:Int,b:Int): Unit ={
    println("===開始指定引數名進行呼叫===")
    println("a的值:"+a)
    println("b的值:"+b)
  }

  // 遞迴函式,求a的階乘
  def factFun(a:BigInt) : BigInt = {
    if (a==1)
     1
    else
    a*factFun(a-1)
  }

  // 高階函式
  def apply(f:Int => String,v:Int) = f(v)
  def layout[A](x:A) = "["+x.toString+"]"

  // 匿名函式
  val multFun = (i:Int,j:Int) => i*j

  // 函式柯里化
  def addFunKe(a:Int)(b:Int) = a+b

  // 閉包:返回值依賴於宣告在函式外部的一個或者多個變數
  var numOne = 10;
  val multOneFun = (a:Int)=>a*numOne
}

Scala常用資料結構一

這一部分不是包含所有的資料結構,只涉及到字串,陣列以及List集合的相關知識。後續的補充會在學習後進行總結。

import Array._
/**
 * Scala常用的資料結構一:字串,陣列,List集合
 * @author: zae
 * @date: 2021/8/19
 * @time: 16:21
 */
object ThreeScala {
  def main(args: Array[String]): Unit = {
    // 呼叫關於字串的方法
    strBuf()
    // 呼叫陣列方法
    arrFun()
    // 呼叫List列表方法
    listFun()
  }

  // 關於字串的相關知識
  def strBuf() = {
    val buf = new StringBuilder;
    buf += 'a'
    buf ++= "bcdef"
    println("buf is : "+buf.toString())

    var str1 = "yyyyyy.com"
    println("yyyyyy.com的長度為"+str1.length())

    var str2 = "琴鍵的空間"
    println("str1和str2的連線結果為"+str1.concat(str2))

    var floatVar = 12.456
    var intVar = 10
    var stringVar = "ZAE"
    var fs = printf("浮點型變數為%f,整型變數為%d,字串為%s",floatVar,intVar,stringVar)
    println(fs)
  }

  // 關於陣列
  def arrFun() = {
    // 第一種宣告陣列的方式
    var z1 = new Array[String](3)
    z1(0) = "java";z1(1) = "python";z1(2) = "scala"

    // 第二種宣告陣列的方式
    var z2 = Array("java","python","scala")

    // 陣列處理
    var myList = Array(1.9,3.8,5,6.1)
    var total = 0.0
    for(i <- 0 to myList.length-1){
      total += myList(i)
    }
    println("陣列的總和為:"+total)

    var maxNum = myList(0)
    for(i <- 0 to myList.length-1){
      if(myList(i)>maxNum)
        maxNum = myList(i)
    }
    println("最大值為:"+maxNum)

    // 多維陣列
    val arrMany = Array.ofDim[Int](3,3)
    for(i<-0 to 2;j<-0 to 2){
      arrMany(i)(j) = i+j
    }
    // 列印二維陣列
    for(i<-0 to 2;j<-0 to 2){
      println("列印二維陣列的結果為:arrMany["+i+"]["+j+"] = "+arrMany(i)(j))
    }

    // 合併陣列
    var myList1 = Array(1,2,3,4)
    var myList2 = Array(5,6,7,8)
    var myList3 = concat(myList1,myList2)
    for(x <- myList3){
      print(x+"|")
    }

    // 區間陣列
    var rangeList1 = range(10,20,2)// 從10-20,每隔2個算一個元素
    var rangeList2 = range(10,20)// 10-20之間所有的整數都是集合元素
    for(x <- rangeList1){
      print(" "+x)
    }
    for (elem <- rangeList2) {
      print(" "+elem)
    }
  }

  // 關於scala - List集合
  def listFun() = {
    // 字串列表(以下為2種寫法,後面同理)
    val site:List[String] = List("Java","python","Scala")
    var siteN = "Java"::("python"::("Scala"::Nil))

    //空列表
    val empty:List[Nothing] = List()
    val emptyN = Nil

    //二維列表
    var dim:List[List[Int]] =
      List(
        List(1,0,0),
        List(0,1,0),
        List(0,0,1)
      )
    var dimR =  (1::(0::(0::Nil))) ::
                (0::(1::(0::Nil))) ::
                (0::(0::(1::Nil))) :: Nil

    println("第一個語言是"+site.head)
    println("最後一個語言是"+site.tail)
    println("列表site是否為空:"+site.isEmpty)
    println("列表empty是否為空"+empty.isEmpty)

    // 連線列表的三種方式
    val word1:List[String] = List("Java","python","Scala")
    val word2:List[String] = List("C","C++","Html")
    // way1:使用:::運算子
    var wordResult = word1:::word2
    // way2:使用List.:::()方法
    wordResult = word1.:::(word2)
    // way3:使用concat方法
    wordResult = List.concat(word1,word2)
    println("word1和word2連線後的結果是:"+wordResult)

    //List.fill()建立一個指定重複數量的元素列表
    val fillList = List.fill(3)("scala")
    println("重複scala三次:"+fillList)

    //List.tabulate() 方法是通過給定的函式來建立列表
    val taListOne = List.tabulate(6)(n=>n*n)
    println("一維:"+taListOne)
    val talListTwo = List.tabulate(3,4)(_*_)
    println("多維:"+talListTwo)
  }
}

第一天就搭建了下環境和學習了下比較基礎簡單的用法,以後可能會愈來愈難,但是一定要堅持下去!