scala基礎語法-----Spark基礎

Alex_81D發表於2020-09-29

scala基本語法

我們可以根據scala 菜鳥教程來學習

地址為:

https://www.runoob.com/scala/scala-tutorial.htm

1.變數宣告

/**

      * 定義變數使用var或者val關 鍵 字

      

      * 語法:

      *  var | val 變數名稱(: 資料型別) =變數值  */

    // 使用val修飾的變數, 值不能為修改,相當於java中final修飾的變數

val name = "tom"

name=”李四”  //錯誤

     // 使用var修飾的變數,值可以修改

var age = 18

age=40  //正確  ,可以修改

    // 定義變數時,可以指定資料型別,也可以不指定,不指定時編譯器會自動推測變數的資料型別

    val name2 : String = "jack"

 

 

 

2.變數宣告字串的格式化輸出

valal name = "JackMa"
 val price = 998.88d
 val url = "www.baidu.com"
 // 普通輸出,注意這裡是可以使用逗號分隔的,但是在java中,我們是需要用“+”號拼接
 println("name=" + name,"price="+price,"url="+url)
 // 'f'插值器允許建立一個格式化的字串,類似於C語言中的printf。
 // 在使用'f'插值器時,所有變數引用都應該是printf樣式格式說明符,如%d ,%i ,%f等 。
 // 這裡$name%s列印String變數name,
 println(f"姓名:$name%s,價格:$price%1.3f,網址:$url%s")
 println(f"姓名:$name,價格:$price,網址:$url")
 // 's'插值器允許在字串中直接使用變數
 // 下列語句中將String型變數($name)插入到普通字串中
 println(s"name=$name,price=$price,url=$url")
 //'s'插值器還可以處理任意形式的表示式
 val m=12;
 val n=33;
 println(s"m+n=${m+n}")
println(s"1+1=${1+1}") //output "1+1=2"

 

3.條件表示式

//if語句的使用
var faceValue=98
var res1=if (faceValue>90) "帥的一批" else "有點惱火"
println(res1)
//3>5 不成立,且程式碼沒有else分支,那麼res2應該輸出什麼呢?
var i=3
var res2=if (i>5) i
println(res2)// output  ()代表空
// 支援巢狀,if...else if ...else程式碼過多時可以使用{}
val score=85
var res3={if(score<60)"不及格"
else if(score>=60&&score<70)"及格"
else if (score>=80&&score<90)"優秀"
else "非常優秀"}
println(f"res3=$res3")

輸出

4.迴圈語句

//  定一個陣列
var arr = Array(1, 2, 3, 4, 5, 6)
//遍歷陣列中麼個元素
for (ele <- arr) {
  print(ele+" ")
} /*output:1 2 3 4 5 6*/
println("")
// 0 to 5 =>會生成一個範圍集合Range(0,1,2,3,4,5),左閉右閉
for (i <- 0 to 5) {
  print(i+" ") /*output:0,1,2,3,4,5*/
}
println("")
// 0 until 5 =>會生成一個範圍集合Range(0,1,2,3,4),左閉右開
for (i <- 0 until 5) {
  print(i+" ")/*output:0,1,2,3,4*/
}
println("")
// for迴圈中可以增加守衛,下面這段語句是列印arr陣列中的偶數
for (i <- arr if i % 2 == 0) {
  print(i+" ")
} /*input:2,4,6*/
println("\n********************雙層for迴圈****************************")
//雙層for迴圈
for (i <- 1 to 3; j <- 1 to 3 if i != j) {
  print(i * 10 + j + "  ")
} /*output:12,13,21,23,31,32*/

for (i <- 1 to 3) {
  for(j <- 1 to 3 if i != j)
   {
     println(i * 10 + j + "")
   }
}

 

輸出:

1 2 3 4 5 6

0 1 2 3 4 5

0 1 2 3 4

2 4 6

********************雙層for迴圈****************************

12  13  21  23  31  32  12

13

21

23

31

32

 

********************yield 關鍵字將滿足條件的e的值又組合成一個陣列****************************

2

4

6

 

4運算子和運算子過載

Scala 中的+-*/%等操作符的作用與 Java 一樣,位操作符 &|^>><<也一樣。

只是有 一點特別的:這些操作符實際上是方法。

例如:

a+b

是如下方法呼叫的簡寫:

a.+(b)

a 方法 b 可以寫成 a.方法(b)

例如

var a=4;
var b=5;
var c=a+b;
var d=a.+(b);
println(c)  //輸出是9
println(d)  //輸出是9

4方法的定義與呼叫

//方法宣告使用關鍵字def .
def f1(): Unit =
{
   //函式體
  println("我是方法體")
}
//方法名為f1.  無引數, 返回值型別為Unit,表示沒有返回值
def  f2(m:Int,n:Int):Int={
  return m+n;
  //或者直接寫m+n  不用帶關鍵字 return
}

//函式呼叫   和java相同

f1();
var m=f2(4,5);
println(m)

//方法體比較簡單的方法還可以如下宣告方式

def sayHello1 = print("Say BB1")
def sayHello2() = print("Say BB2")
sayHello1 // 如果方法沒有()呼叫時不能加()
sayHello2() // 可以省略( ) ,也可以不省略

 

4函式的定義與呼叫

函式宣告使用val關鍵字,類似宣告變數

val m1=  println("我是m1函式")
val m2:(Int,Int)=>Int=(x,y)=>{  x+y }
val m3:(Int,Int)=>Unit=(x,y)=>{  var z=x+y;println(z)}
val m4=(x:Int)=>{x+4;}

 

注意:

方法與函式的區別

  1. 宣告方式不同
  2. 函式可以作為方法的引數

通過  Val  函式=方法 _   把方法轉為函式

 

//宣告一個引數為函式的方法, 第一個引數是函式名,第二個引數是引數

Func:Int=>Int   前面的Int表示函式的引數Int型別, 後面的Int表示函式的返回值是Int型別
def cal(func:Int=>Int,x: Int): Unit ={
   var r= func(x);
   println(r)
}

(func:Int引數名稱和型別,Int,x: Int 返回值型別和返回值引數)

例如:如下方法可以作為cal方法的引數

def f1(x:Int): Int ={
  x+10;
}

呼叫cal方法 .注意這裡的f1是方法,可以直接作為函式的引數,

系統預設f1轉為函式。

cal(f1,4);

也可以使用這樣, 先轉為函式,後傳值。

val f1_m=f1 _;
cal(f1_m,4);

5可變引數

格式. 注意後面的*  ,  params是任意的一個變數。在函式內部就是一個陣列了。可以接受多個引數。

//說白了,可變引數就是使用一個陣列取接收值

 

def m2(params: Int *): Unit ={
   for(x<-params){
     println(x)
   }
}

 

 

練習程式碼:

object C1 {
  def main(args: Array[String]): Unit = {
//    1、基礎變數
     val name="zhh"
    //name="zzz" //錯誤 val不能修改
    var name3="zhh" //var可修改
    name3="zzz"
    val name2:String="jack"
//    2、變數宣告字串的格式化輸出
    val age=18
    val address="desfsff"
    println("name1="+name,"age1="+age,"address="+address)
    println(f"name2=$name%s,age2=$age%s,address=$address%s")
    println(f"name3=$name ,age3=$age,address=$address%s")
    println(s"name4=$name ,age4=$age,address=$address")
    var m=100
    var n=3
    println(s"m/n=${m/n}")
    println(s"m/n=${m*1.0/n}")
 
    var i=3
    var res=if (i>5) i
//3、迴圈遍歷
    var a1=Array(1,2,3,4,5,6);
    for(v <- a1) //<-迴圈遍歷a1 將每次遍歷的值賦值給v
      {
        print(v+" ")
      }
    println()
    a1.foreach(v => print(v+" "))   //v相當於函式引數,print(v+" ")相當於函式體 (相當於匿名函式,,,整體類似於函式function(v){})
    println()
 
    for(i <- 1 to 3)
      {
        print(i+" ")
      }
    println()
 
     //    輸出陣列a1的內容
    for(i <- 0 to a1.length-1)
    {
      print(a1(i)+" ") //用a1(i)表示陣列元素
    }
    println()
 
    for(i <- a1 if i%2 ==0 )
    {
      print(i+" ") //if i%2 ==0 限制輸出條件
    }
    println()
 
    //雙層for迴圈
    for (i <- 1 to 3; j <- 1 to 3 if i != j) {
      print(i * 10 + j + " ")
    } /*output:12,13,21,23,31,32*/
    println()
//     與上面迴圈等價
    for (i <- 1 to 3) {
      for(j <- 1 to 3 if i != j)
      {
        print(i * 10 + j + " ")
      }
    }
    println()
//4、方法
    var c2=new C2(); //例項物件
    c2.f1();
// 5、函式
    //此處為main函式中內容
    println("我是main函式的內容")
    f2();
    m3(3,4)  //帶引數的函式需要呼叫(一般不這樣用)
 
   //......(1)顯式轉換
    val f3_hanshu=f3 _;  //顯式轉換 方法f3轉換為函式
    cal(f3_hanshu,20);
    //.....顯式轉換結束
 
    //....(2)隱式轉換
    cal(f3,20);  //20作為f3的引數傳給方法f3
//    呼叫cal方法 .注意這裡的f1是方法,可以直接作為函式的引數,
//    系統預設f1轉為函式。
//.....隱式轉換結束
 
 
    //(3)可變引數
   m2(canshu  =1,3,4,5,2,5);
 
 
 
 
  }
 
//顯式轉換,隱式轉換。。。。。。。
  def f3(m:Int): Int ={  //f3作為引數傳給方法cal,即f3為引數fun1,
    return m+10;
  }
 
  def cal (fun1: Int=>Int,m:Int) : Unit ={  //func:Int引數名稱和型別,Int,x: Int 返回值型別和返回值引數
    var t=fun1(m);
    println(t)
  }
  //顯式轉換結束,隱式轉換結束。。。。。
 
 
  //可變引數..............
  def m2(canshu : Int *): Unit ={
    for(x<-canshu ){
      print(x+" ")
    }
    println()
  }
  //說白了,可變引數就是使用一個陣列取接收值,func此時相當於一個陣列
  可變引數結束..............
 
  // 5、函式
  //程式會先執行hashu,和hanshu2(val 一個函式相當於已經例項化類似於是個變數) 後執行main函式!!!!!
 
  def f2(): Unit ={
    println("我是方法f2")
  }
 
  def f1(x:Int,y:Int): Int ={
    return x+y;
  }
 
  val hanshu=println("我是函式hanshu")
  val hanshu2={println("我是函式hanshu2222")}
  val m3:(Int,Int)=>Int=(x,y)=>{  //帶參函式
    println("dsfdfsfsff")
    x+y
  } //m3是函式名稱,(Int,Int)函式的引數型別,Int是返回值型別 (x,y)返回值引數,{  x+y }為返回值
 
}
    package com.zhh
     
    class C2 {
      //   4、方法宣告
      def f1(): Unit ={
        println("我是C2.f1")
        var t=f2(n1=3,n2=4) //呼叫方法f2
        println(t)
     
      }
     
      def f2(n1:Int,n2:Int): Int ={
    //    不能改變n1的值,可用用另一個變數賦予n1的值
        var m=n1;
        m=222;
        return n1+n2
      }
     
     
    }

結果為:

我是函式hanshu
我是函式hanshu2222
(name1=zhh,age1=18,address=desfsff)
name2=zhh,age2=18,address=desfsff
name3=zhh ,age3=18,address=desfsff
name4=zhh ,age4=18,address=desfsff
m/n=33
m/n=33.333333333333336
1 2 3 4 5 6 
1 2 3 4 5 6 
1 2 3 
1 2 3 4 5 6 
2 4 6 
12 13 21 23 31 32 
12 13 21 23 31 32 
我是C2.f1
7
我是main函式的內容
我是方法f2
dsfdfsfsff
30
30
1 3 4 5 2 5 

 

 

常量和變數

val宣告出來的為常量,不能再次賦值;可以省略型別,scala會自動推導。

var宣告出來的為變數,可以再次賦值;可以省略型別,scala會自動推導。

var a = "xxx"; 等同於 var a : String = "xxx";

a = "String 2";

val b = 2;

b = 3; // 會出錯

宣告多個變數:

val a, b = "xxx"; // a, b的值都是 "xxx"

scala的常用資料型別:

Byte:內建轉換為scala.runtime.RichByte

Char:內建轉換為scala.runtime.RichChar

Short:內建轉換為scala.runtime.RichShort

Int:內建轉換為scala.runtime.RichInt

Long:內建轉換為scala.runtime.RichLong

Float:內建轉換為scala.runtime.RichFloat

Double:內建轉換為scala.runtime.RichDouble

Boolean:內建轉換為scala.runtime.RichBoolean

這些型別都是類,Scala並不區分基本型別與引用型別。

與java基本型別相對應,但擁有更多的方法,因為會轉換為相應的RichXxxx,在轉換後的類裡新增scala語言層面的方法。

例如:

  1.toLong,其中1會被轉換為RichInt型別的例項。

  1.to(5)會產生Range(1, 2, 3, 4, 5)

任意有窮數字:

BigInt:

BigDecimal:

字串:

String:對應於scala.collection.immutable.StringOps

型別轉換

使用方法,沒有強制轉換一說。

如:var a : Int = 1

  var b : Long = a.toLong

操作符過載

val value = 8 + 5

其中,+ 這些操作是方法。

完整的是val value = (8).+(5);

(8)轉換成Int物件,呼叫Int物件的+方法(方法名為+)。

沒有++,--操作符,因為相應型別是不可變的。

Scala方法呼叫的簡略寫法

方法的簡略寫法:

  a 方法 b

完整寫

  a.方法(b)

例:1.to(2),可簡略寫為1 to 2

apply方法:

  a(b)

完整為

  a.apply(b)

例: "xxx"(2) 實際轉換為 "xxx".apply(2)

常用來構造物件

方法作為引數:

匿名方法:

  x, y => x + y 或

   + 

x, y 表示為引數;=>指向方法體;x + y計算和並返回。

+ 中,第一個“”表示第一個引數,第二個“”表示第二個引數。

例:"sU".count(_.isUpper)

  "sU".count(x => x.isUpper)

import

import math._

作用是匯入scala.math包下所有類和物件。以scala.開頭的包可以省略。

單例物件object

object定義的物件為單例,可以直接使用 物件名.方法(引數) 進行呼叫,類似java中的static方法。

伴生物件:擁有與class類同名的object定義的物件。

Scala doc

http://scala-lang.org/api

數學函式位於scala.math包中,而不是位於某個類中;

使用數值型別,使用RichInt、RichDouble等;

使用字串,使用StringOps;