scala Learning

  • Scala 與 Java 的最大區別是:Scala 語句末尾的分號 ; 是可選的。
  • 大小寫敏感
  • 類名第一個字母大寫
  • 方法名第一個字母小寫
  • 定義包 package
  • 引入包 import java.awt._ // 引入包內所有成員

基本數據類型和操作

基本數據類型

Scala的數據類型包括:Byte、Char、Short、Int、Long、Float、Double和 Boolean。對於字符串,Scala用java.lang.String 類來表示字符串。

操作符

  • 在Scala中,可以使用加(+)、減(-) 、乘(*) 、除(/) 、餘數(%)等操作 符,而且,這些操作符就是方法。例如,5 + 3和(5).+(3)是等價的。

  • 在Scala中並沒有提供++和–操作符。

富包裝類

  • 對於基本數據類型,除了以上提到的各種操作符外,Scala 還提供了許多常用運算的方法,只是這些方法不是在基本類 裏面定義,還是被封裝到一個對應的富包裝類中

  • 每個基本類型都有一個對應的富包裝類,例如Int有一個 RichInt類、String有一個RichString類,這些類位於包 scala.runtime中

  • 當對一個基本數據類型的對象調用其富包裝類提供的方法, Scala會自動通過隱式轉換將該對象轉換爲對應的富包裝類 型,然後再調用相應的方法。例如:3 max 5

Range

可以用一下命令來產生for循環時的數值序列:

1 to 5 
1 util5
1 to 10 by 2

輸入

import scala.io._. // read_xxx 在這個包中
var i = readInt()
var l = readLine()
var c = readChar()
var b = readBoolean()

輸出

print()println()printf()

讀寫文件

  • Scala 進行文件寫操作,直接用的都是 java中 的 I/O 類 (java.io.File)
import java.io._

object Test {
   def main(args: Array[String]) {
      val writer = new PrintWriter(new File("test.txt" ))

      writer.write("菜鳥教程")
      writer.close()
   }
}

  • 可以使用Scala.io.Source的getLines方法實現對文件中所 有行的讀取
import scala.io.Source

object Test {
   def main(args: Array[String]) {
      println("文件內容爲:" )
			
     	// 1. 
      Source.fromFile("test.txt" ).foreach{ 
         print 
      }
     // 2.返回結果是個迭代器
     Source.fromFile("test.txt" ).getlines 
   }
}

控制結構

條件: if

if(布爾表達式 1){
   // 如果布爾表達式 1 爲 true 則執行該語句塊
}else if(布爾表達式 2){
   // 如果布爾表達式 2 爲 true 則執行該語句塊
}else if(布爾表達式 3){
   // 如果布爾表達式 3 爲 true 則執行該語句塊
}else {
   // 如果以上條件都爲 false 執行該語句塊
}

循環:While/do…while/for

for( a <- 1 to 10){
	println( "Value of a: " + a );
}

for( a <- 1 to 3; b <- 1 to 3){
 	println( "Value of a: " + a );
	println( "Value of b: " + b );
}

val numList = List(1,2,3,4,5,6);
for( a <- numList ){
  println( "Value of a: " + a );
}

//for 循環過濾
for( a <- numList if a != 3; if a < 8 ){
  println( "Value of a: " + a );
}

//for 使用 yield
var retVal = for{ a <- numList 
                 if a != 3; if a < 8
                }yield a

數據結構

容器(Collection)

  • Scala提供了一套豐富的容器(collection)庫,包括列表 (List)、數組(Array)、集合(Set)、映射(Map)等
  • 根據容器中元素的組織方式和操作方式,可以區分爲有序 和無序、可變和不可變等不同的容器類別
  • Scala用了三個包來組織容器類,分別是scala.collection 、 scala.collection.mutable(可變集)和scala.collection.immutable(不可變集)
  • 它爲所有的容器類定義了公用的foreach 方法,用於對容器元素進行遍歷操作

列表(List):

Scala 列表類似於數組,它們所有元素的類型都相同,但是它們也有所不同:列表是不可變的,值一旦被定義了就不能改變,其次列表 具有遞歸的結構(也就是鏈接表結構)而數組不是。。

幾個要知道的符號:

  • 列表的元素類型 T 可以寫成 List[T]
  • 構造列表的兩個基本單位是 Nil::Nil 也可以表示爲一個空列表。

定義

有兩種方式:

// 字符串列表
val site: List[String] = List("Runoob", "Google", "Baidu")
val site = "Runoob" :: ("Google" :: ("Baidu" :: Nil))

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

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

列表基本操作

  • head 返回列表第一個元素
  • tail 返回一個列表,包含除了第一元素之外的其他元素
  • isEmpty 在列表爲空時返回true
println( "第一網站是 : " + site.head )
println( "最後一個網站是 : " + site.tail )
println( "查看列表 site 是否爲空 : " + site.isEmpty )

連接列表

可以使用 ::: 運算符或 List.::😦) 方法或 List.concat() 方法來連接兩個或多個列表。

// 使用 ::: 運算符
var fruit = site1 ::: site2
println( "site1 ::: site2 : " + fruit )

// 使用 List.:::() 方法
fruit = site1.:::(site2)
println( "site1.:::(site2) : " + fruit )

// 使用 concat 方法
fruit = List.concat(site1, site2)
println( "List.concat(site1, site2) : " + fruit  )

Scala List 常用方法

  • List.fill(): 我們可以使用 List.fill() 方法來創建一個指定重複數量的元素列表:

    val site = List.fill(3)("Runoob") // 重複 Runoob 3次
    println( "site : " + site  )
    
    val num = List.fill(10)(2)         // 重複元素 2, 10 次
    println( "num : " + num  )
    
  • List.tabulate() 方法是通過給定的函數來創建列表。

    方法的第一個參數爲元素的數量,可以是二維的,第二個參數爲指定的函數,我們通過指定的函數計算結果並返回值插入到列表中,起始值爲 0,實例如下:

    // 通過給定的函數創建 5 個元素
    val squares = List.tabulate(6)(n => n * n)
    println( "一維 : " + squares  )
    
    // 創建二維列表
    val mul = List.tabulate( 4,5 )( _ * _ )      
    println( "多維 : " + mul  )
    

    輸出:

    一維 : List(0, 1, 4, 9, 16, 25)
    多維 : List(List(0, 0, 0, 0, 0), List(0, 1, 2, 3, 4), List(0, 2, 4, 6, 8), List(0, 3, 6, 9, 12))
    
// +: 爲列表添加元素 (:朝着list)
"xxx"+:site // 返回:List(xxx, Runoob, Google, Baidu) 

// :+ 
site :+ "xxx" // 返回 List[String] = List(Runoob, Google, Baidu, xxx)

// :: 在列表開頭添加元素
"xxx"::site  // 返回:List(xxx, Runoob, Google, Baidu)

// :::在列表開頭添加指定列表的元素
site ::: nums // val res35: List[Any] = List(Runoob, Google, Baidu, 1, 3, 2)

// ++ 拼接
site++nums  // 返回:val res34: List[Any] = List(Runoob, Google, Baidu, 1, 3, 2)

// ++:和:++
site :++ nums // val res31: List[Any] = List(Runoob, Google, Baidu, 1, 3, 2)
site ++: nums // val res29: List[Any] = List(Runoob, Google, Baidu, 1, 3, 2)

site.apply(2) // apply 通過列表索引獲取元素
// val res42: String = Baidu
site.contains("baidu")
// val res43: Boolean = false
val nums = List(1,1,2,3); nums.distinct
// val res45: List[Int] = List(1, 2, 3)
nums.exists(x=>x>1)  // 判斷列表中指定條件的元素是否存在。
// val res47: Boolean = true
nums.filter(x=>x>1)  // 輸出符號指定條件的所有元素。
//val res48: List[Int] = List(2, 3)
site.foreach(print(_)) // 將函數應用到列表的所有元素
// RunoobGoogleBaidu
site.indexOf("Baidu")
//val res69: Int = 2
site.map(x=>x+"xxx")
// val res71: List[String] = List(Runoobxxx, Googlexxx, Baiduxxx)
site.mkString(";")  // 使用分隔符將列表所有元素作爲字符串顯示
// val res74: String = Runoob;Google;Baidu
site.mkString  // 列表所有元素作爲字符串顯示
// val res75: String = RunoobGoogleBaidu
site.reverse
// val res77: List[String] = List(Baidu, Google, Runoob)

site.toString()
// val res86: String = List(Runoob, Google, Baidu)

集合(Set)

  • 集合包括可變集不可變集
  • 默認是不可變的,如果要聲明一個可變集,則需要提前引入scala.collection.mutable.Set
import scala.collection.mutable.Set // 可以在任何地方引入 可變集合
val mutableSet = Set(1,2,3)
// val mutableSet: scala.collection.mutable.Set[Int] = HashSet(1, 2, 3)
mutableSet.add(4)
mutableSet.remove(1)

num1 & num2  // 交集 或者.&或.intersect 取交集
// val res97: scala.collection.mutable.Set[Int] = HashSet(20, 9)
num1 &~ num2 // 差集
//val res98: scala.collection.mutable.Set[Int] = HashSet(5, 6, 45, 30)
num2 &~ num1 // 差集
//val res99: scala.collection.mutable.Set[Int] = HashSet(50, 35, 55, 60)

num1 ++ num2 // 連接集合
// val res101: scala.collection.mutable.Set[Int] = HashSet(35, 5, 6, 9, 45, 50, 20, 55, 60, 30)

映射(Map)

  • Map 有兩種類型,可變與不可變,區別在於可變對象可以修改它,而不可變對象不可以。
  • 默認情況下 Scala 使用不可變 Map。如果你需要使用可變集合,你需要顯式的引入 import scala.collection.mutable.Map
  • 更多參考API
// 空哈希表,鍵爲字符串,值爲整型
var A:Map[Char,Int] = Map()

// Map 鍵值對演示
val colors = Map("red" -> "#FF0000", "azure" -> "#F0FFFF")

println( "colors 中的鍵爲 : " + colors.keys )
println( "colors 中的值爲 : " + colors.values )
println( "檢測 colors 是否爲空 : " + colors.isEmpty )

colors.keys.foreach{ i =>  
   										print( "Key = " + i )
   										println(" Value = " + colors(i) )}
colors.toSet
// val res106: scala.collection.immutable.Set[(String, String)] = Set((red,#FF0000), (azure,#F0FFFF))

迭代器(Iterator)

  • 在Scala中,迭代器(Iterator)不是一個集合,但是,提供了 訪問集合的一種方法
  • 迭代器包含兩個基本操作:nexthasNext。next可以返回迭代器的下一個元素,hasNext用於檢測是否還有下一個元素
val it = Iterator("Baidu", "Google", "Runoob", "Taobao")
      
while (it.hasNext){
      println(it.next())
}
it.size
it.length

數組(Array)

  • 數組是一種可變的、可索引的、元素具有相同類型的數據集合,它是各種高 級語言中最常用的數據結構。
  • Scala提供了參數化類型的通用數組類Array[T], 其中T可以是任意的Scala類型,可以通過顯式指定類型或者通過隱式推斷來 實例化一個數組。
  • Array提供了函數ofDim來定義二維和三維數組
  • 採用Array類型定義的數組屬於定長數組,其數組長度在初始化後就不能改變。如果要定義變長數組,需要使用ArrayBuffer參數類型,其位於包 scala.collection.mutable中。
  • 更多參考
import Array._
// 定義1
var z = Array("Runoob", "Baidu", "Google")
// 定義2
var z = new Array[String](3)
z(0) = "Runoob"; z(1) = "Baidu"; z(4/2) = "Google"
// 輸出所有數組元素
for ( x <- myList ) {
  println( x )
}
myList.length

// 多維數組,通過ofDim定義
var myMatrix = ofDim[Int](3,3)    
for (i <- 0 to 2) {
  for ( j <- 0 to 2) {
    myMatrix(i)(j) = j;
  }
}

// 合併數組
var myList3 =  concat( myList1, myList2)

元組(Tuple)

  • 與列表一樣,元組也是不可變的,但與列表不同的是元組可以包含不同類型的元素。
  • 目前 Scala 支持的元組最大長度爲 22。
  • 我們可以使用 t._1 訪問第一個元素, t._2 訪問第二個元素
val t = (1, 3.14, "Fred")  
val t = (4,3,2,1)
val sum = t._1 + t._2 + t._3 + t._4  // 訪問元祖元素;返回10
t.productIterator.foreach{ i =>println("Value = " + i )} //Tuple.productIterator() 迭代輸出元組的所有元素

Option

  • Scala Option(選項)類型用來表示一個值是可選的(有值或無值)。
  • Option[T] 是一個類型爲 T 的可選值的容器: 如果值存在, Option[T] 就是一個 Some[T] ,如果不存在, Option[T] 就是對象 None 。
  • 可以使用 getOrElse() 方法來獲取元組中存在的元素或者使用其默認的值,
val myMap: Map[String, String] = Map("key1" -> "value")
val value1: Option[String] = myMap.get("key1")  // Some("value1")
val value2: Option[String] = myMap.get("key2")  // None

def show(x: Option[String]) = x match {
      case Some(s) => s
      case None => "?"
   }
print(show(value1) )  // value
print(show(value2) )  // ? 

value1.getOrElse(0) // value
value2.getOrElse(0) // 0

value1.filter(_=="value") 
// val res6: Option[String] = Some(value)

面向對象編程基礎

Scala 方法與函數

  • Scala 有方法與函數,二者在語義上的區別很小。Scala 方法是類的一部分,而函數是一個對象可以賦值給一個變量。換句話來說在類中定義的函數即是方法。
  • Scala 中的函數則是一個完整的對象,Scala 中的函數其實就是繼承了 Trait 的類的對象。
  • Scala 中使用 val 語句可以定義函數,def 語句定義方法。

方法

  • 方法定義由一個 def 關鍵字開始,緊接着是可選的參數列表,一個冒號 : 和方法的返回類型,一個等於號 = ,最後是方法的主體。
  • 如果方法沒有返回值,可以返回爲 Unit,這個類似於 Java 的 void,
def functionName ([參數列表]) : [return type]  // 聲明

def functionName ([參數列表]) : [return type] = {  // 定義
   function body
   return [expr]
}

// 舉例
object Test {
   def main(args: Array[String]) {
        println( "Returned Value : " + addInt(5,7) );
   }
   def addInt( a:Int, b:Int ) : Int = {
      var sum:Int = 0
      sum = a + b

      return sum
   }
}

class Point(xc: Int, yc: Int) {
   var x: Int = xc
   var y: Int = yc

   def move(dx: Int, dy: Int) {
      x = x + dx
      y = y + dy
      println ("x 的座標點: " + x);
      println ("y 的座標點: " + y);
   }
  
  def increment():Unit = {x += 1}
  def current(): Int = {value} // 如果操作語句只有一句
}

object Test {
   def main(args: Array[String]) {
      val pt = new Point(10, 20);

      // 移到一個新的位置
      pt.move(10, 10);
   }
}

對象

單例對象

  • Scala並沒有提供Java那樣的靜態方法或靜態字段,但是,可以採用 object關鍵字實現單例對象,具備和Java靜態方法同樣的功能。

在這裏插入圖片描述

伴生對象

  • 在Java中,我們經常需要用到同時包含實例方法和靜態 方法的類,在Scala中可以通過伴生對象來實現。
  • 當單例對象與某個類具有相同的名稱時,它被稱爲這個 類的“伴生對象”。
  • 類和它的伴生對象必須存在於同一個文件中,而且可以 相互訪問私有成員(字段和方法)。

繼承

Scala繼承一個基類跟Java很相似, 但我們需要注意以下幾點:

  • 1、重寫一個非抽象方法必須使用override修飾符。
  • 2、只有主構造函數纔可以往基類的構造函數裏寫參數。
  • 3、在子類中重寫超類的抽象方法時,不需要使用override關鍵字。

特質

模式匹配

函數式編程

實例WordCount:

import java.io.File
import scala.io.Source
object WordCount{
  def main(args:Array[String]):Unit={
    val dirfile=new File("wordCount")
    val files = dirfile.listFiles
    for(file <- files) print(file)
    val listFiles = files.toList
    val wordsMap = scala.collection.mutable.Map[String,Int]()
    listFiles.foreach(file => Source.fromFile(file).getLines().foreach(line => line.split(" ").foreach(
      word => {
        if(wordsMap.contains(word)){
          wordsMap(word) += 1
        }else{
          wordsMap+=(word->1)
        }
      }
    )))
  println(wordsMap)
  for((key,value)<-wordsMap) print(key + ": " + value)
  }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章