scala筆記

1.建立Array
// array 建立方法1
val arr = new Array[String](3)
arr(0) = "1"
arr(0) = "x"
//底層調用 def update(i: Int, x: T) { throw new Error() }
arr(1) = "1"
arr(2) = "2"
println(arr.mkString(","))
//x,1,2
// array 建立方法2
val arr2 = Array("x","y","z")
println(arr2.mkString(","))
//x,y,z
2.list
 
//建立列表
val oneTwo = List(1, 2)
val threeFour = List(3, 4)
//將oneTwo 中的元素所有加到threeFour 前部
val oneTwoThreeFour = oneTwo ::: threeFour
val twoThree = List(2, 3)
//:: 是右操做數twoThree 的方法
val oneTwoThree = 1 :: twoThree
 
//list 的經常使用方法
oneTwoThreeFour.count(_ % 2 == 0) //統計偶數的數量
oneTwoThreeFour.drop(2) //返回丟棄前兩個元素的list
oneTwoThreeFour.exists(_ == 2) // 是否存在元素2
oneTwoThreeFour.filter(_ % 2 != 0) //過濾出奇數
oneTwoThreeFour.forall(_ % 2 == 0) //list中是否全是偶數
oneTwoThreeFour.head // list 第一個元素
oneTwoThreeFour.tail// 返回除第一個元素的其餘元素組成的list
oneTwoThreeFour.init//除最後一個元素的list
oneTwoThreeFour.last// 最後一個元素
oneTwoThreeFour.reverse //list 反轉
oneTwoThreeFour.sortWith((x, y) => x < y) //list 排序
list一經建立就不可變,裏面的值也不可變
list 不提供append 方法,由於隨着列表長度的增長,append 方法(會不斷的建立的新數組,複製上一個列表的值進去)的操做時間呈線性增加,而 :: 方法的時間是固定的
3.元組
val tp = (1,2,"salary")
println(tp._2)
元組中能夠存放不一樣類型的元素,(1,2,"salary") 存放了(int,int,String)類型的值,能夠用於返回不一樣類型組合的返回值。
爲何不用 tp(0) 這種方式取值?由於tp中的每一個元素的類型不是固定的
4.set and map
 
val set = Set(1, 2, 3, 5) //不能夠調用 += 方法,除非將set 聲明爲var
val set2 = scala.collection.mutable.Set.empty[Int]
set2 += 1
set2 += 2
set2 ++= set
println(set2)
//Set(1, 5, 2, 3)
val map = Map("x" -> 1, "z" -> 2)
val map2 = scala.collection.mutable.Map.empty[String, Int]
map2 += "x" -> 1
map2 += "y" -> 2
map2 ++= map
println(map2)
//Map(z -> 2, y -> 2, x -> 1)
 
5.讀取文件
 
val lines = Source.fromFile(filename).getLines().toList //若是不調用toList 方法,則返回的是 Iterator ,只能遍歷一遍
val line = lines.reduceLeft((x, y) => if (x.length > y.length) x else y)
println(line)
println("=" * 30)
lines.foreach(println)
 
Michael, 15
==============================
Michael, 15
Andy, 30
Justin, 19
 
6.scala 中定義反作用方法
一般scala用以下方式定義帶反作用的方法,相似java中的方法定義,這樣的定義默認返回值類型是Unit,所以函數末尾雖然寫了 "s" ,s也會被轉化爲Unit
 
def sideEffectFunc(s: String) {
  println(s)
  s
}
 
7.scala 的每一個源文件都隱含了對包java.lang、 包scala,以及單例對象Predef的成員的引用,PreDef 包含了許多有用的方法,例如println 語句 實際調用了 Predef 的  def println(x: Any) = Console. println (x),能夠看到它又調用了Console。println(x) 方法
8.App 特質,繼承App 能夠省去不少代碼編寫工做,沒必要編寫main類,就可直接運行
 
import scala.App
 
object Test2 extends App {
  println("jaosn")
}
 
9.scala 對象相等性比較
scala 中 "==" 與java 中的 equal 相似,比較的是對象的內容,eq  ne 比較的是對象的引用地址是否相同
"==" 比較邏輯:先看左操做數是否爲null ,若不是null 則調用左操做數的 equal 方法比較,所以scala 能夠省去判斷是否爲null
 
10.
scala 編譯器會把類內部既不是字段也不是方法定義的代碼編譯 到 主 構造器中
 
11.scala 裏每一個輔助構造器的第一個動做都是調用同類的別的構造器(包括主構造器),即都是以 this(……)開始的,也就是說每一個構造器調用終將結束於對主構造器的調用,所以主構造器是類的惟一入口
 
12.scala中的常量,習慣命名方式是駝峯命名法,首字母大寫 好比:MaxValue
 
13.一個案例
class Rational(n: Int, d: Int) {
  require(d > 0)
  private val g = gcd(n.abs, d.abs)
  val numer = n / g
  val denom = d / g
 
  def this(i: Int) = this(i, 1)
 
  def +(that: Rational): Rational = new Rational(numer * that.denom + that.numer * denom, denom * that.denom)
 
  def -(that: Rational): Rational = new Rational(numer * that.denom - that.numer * denom, denom * that.denom)
 
  def *(that: Rational): Rational = new Rational(numer * that.numer, denom * that.denom)
 
  def /(that: Rational): Rational = new Rational(numer * that.denom, denom * that.numer)
 
  override def toString: String = {
    if (denom == 1) s"$numer" else s"$numer / $denom"
  }
 
  private def gcd(a: Int, b: Int): Int = {
    if (b == 0) a else gcd(b, a % b)
  }
}
 
object Rational {
  def main(args: Array[String]): Unit = {
    //隱式轉換,解釋器會自動將int 類型轉換爲Rational
    implicit def intToRational(i: Int): Rational = {
      new Rational(i)
    }
 
    val r = new Rational(2, 3)
    println(4 + r)
    println(r + 4)
  }
}
 
14.scala 中的賦值語句返回值爲 Unit ,所以 while ((line = in.readLine())!= "") 永遠返回true
15.帶過濾器的for
 
for (i <- 1 to 10 if i % 2 == 0; if i != 4) {
  println(i)
}
16.for嵌套循環
 
for (i <- 1 to 9 ;j <- 1 to i) {
  print(s" $j * $i = ${i*j} ")
  if(i==j) println()
}
17.yield 表達式
 
val seq = for (i <- 1 to 10) yield {
  val j = if (i % 2 == 0) i * 2 else i * 3
  i * j
}
 
18.try catch 捕獲異常
try{
  val file = new File("aa")
}catch {
  case ex:FileNotFoundException => println("aa not exists")
  case ex => ex.printStackTrace()
}
19.帶返回值的try catch
 
def getUrl(url: String) = try {
  new URL(url)
} catch {
  case ex => new URL("www.baidu.com")
}
20.重複參數
 
def echo(args: String*): Unit = {
  args.foreach(println)
}
能夠將方法的最後一個參數定義爲重複參數,方法是再類型後加 * ,實際上atgs* 類型是 Array[String],可是傳參的時候卻不能傳 數組 ,好比:val arr = Array("a","b");echo(arr),此時會報錯,正確的寫法是 echo(arr:_*)
 
21.scala.util.Try
def testTry(): Unit ={
  val tt = Try(24/2)
  tt match {
    case Success(a) => println(a)
    case Failure(a) => a.printStackTrace()
  }
}
 
22.抽象類
 
abstract class Element {
  def contents: Array[String]
}
抽象類class 關鍵字前必須帶有  abstract ,不帶 = 和方法體的方法即爲抽象方法,抽象方法不用帶 abstract
 
23.訪問字段值比調用方法略快,由於字段值在類初始化時就已經預先計算,而方法在每次調用時都要計算,可是字段值佔用的空間略大
24.scala 建議將沒有參數且不帶反作用的方法定義成無參數方法風格(不帶括號的方法),將不帶參數可是有反作用的方法定義成空括號方法。千萬不要將不帶參數且有反作用的方法定義成無參數方法風格,午飯方法的訪問相似訪問屬性,客戶會奇怪,爲何這個屬性具備反作用
 
25.繼承
 
class ArrayElements(conts: Array[String]) extends Element {
  override def contents: Array[String] = conts
}
繼承表示超類的全部的成員都屬於子類,如下兩種狀況除外,1.超類的私有成員,2.被子類重寫的超類成員
scala 中若是超類的成員是具體,非抽象的,子類重寫該成員時必須加override 關鍵詞,若是是抽象的,則可加可不加
 
26.若是屬性或方法不但願子類重寫,則能夠加final 關鍵字,如
 
final def height: Int = contents.length
 
27.scala 繼承建議:將子類寫在抽象類的伴生對象中,並定義爲private,抽象類伴生對象中定義建立子類的工廠方法
28.scala 的根類是Any
Any 有兩個子類:AnyVal 和AnyRef,AnyVal 是每一個內建值類的父類,有9個這樣的值類,Byte,Short,Char,Int,Long,Float,Double,Boolean,Unit,前八個對應了java的八個基本類型,運行時會轉換成java的八大基本類型,他們不能用new I建立,由於他們時abstract 且是final的
第九個 是 Unit,至關因而java中的void,它的值是 「()」,
AnyRef 是全部引用類的基類
 
28.scala.Null 是null引用對象的類型,它是每一個引用類(繼承自AnyRef)的子類,null 不兼容值類型。Nothing 位於scala 層級的最底層,是任何其餘類型的子類型,Nothing類型沒有任何值,Nothing 一般用於不正常的終止,好比error
 
29.trait的使用,除了如下兩點外,與類的使用無別
1)特質不能有「類」參數, 好比 trait Foo(i:Int){} ,編譯會報錯
2)在類中super 調用是靜態綁定的,而在trait中super 的調用是動態綁定的,在定義特質的時候,super調用方法的實現還沒有被定義
 
30. Ordered 特質
在開發中咱們常常要用到比較,比較無非 <,> ,<= ,>=無論哪一個類,這四種比較的邏輯都不會改變,scala 提供了Ordered特質來幫助類實現比較,咱們惟一要作的就是混入 Ordered[C] 特質(C 是要比較的類),讓後實現compare 方法,this < that 則返回 <0 的值,相等返回 0,
 
31.特質的堆疊使用
 
package com.program
 
import scala.collection.mutable.ArrayBuffer
 
abstract class IntQueue {
  def get: Int
 
  def put(i: Int)
 
  def hasNext: Boolean
}
 
class BasicIntQueue extends IntQueue {
  private val queue = new ArrayBuffer[Int]()
 
  override def get: Int = queue.remove(0)
 
  override def put(i: Int): Unit = {
    println(s"i 的值是:$i")
    queue += i
    println(s"值添加完畢")
  }
 
  override def hasNext: Boolean = {
    queue.size > 0
  }
}
 
trait Doubling extends IntQueue {
  abstract override def put(i: Int): Unit = {
    println(s"double 前 ")
    super.put(i * 2)
    println(s"double 後 ")
  }
}
 
trait Incement extends IntQueue {
  abstract override def put(i: Int): Unit = {
    println(s"increment 前 ")
    super.put(i + 1)
    println(s"increment 後 ")
  }
}
 
trait Filter extends IntQueue {
  abstract override def put(i: Int): Unit = {
    println(s"filter 前")
    if (i > 0) super.put(i)
    println(s"filter 後")
  }
}
 
class Foo1 {
  def foo(): Unit = {
    println("foo1")
  }
}
 
class Foo2 extends Foo1 {
  override def foo(): Unit = {
    println("foo2 前")
    super.foo()
    println("foo2 後")
  }
}
 
class Foo3 extends Foo2 {
  override def foo(): Unit = {
    println("foo3 前")
    super.foo()
    println("foo3 後")
  }
}
 
object Test2 extends App {
  val myqueue = new BasicIntQueue with Doubling with Incement with Filter
  myqueue.put(1)
  myqueue.put(1)
  myqueue.put(2)
  while (myqueue.hasNext) {
    println(myqueue.get)
  }
 
  println("=" * 20)
  val foo = new Foo3
  foo.foo()
}
 
filter 前
increment 前
double 前
i 的值是:4
值添加完畢
double 後
increment 後
filter 後
filter 前
increment 前
double 前
i 的值是:4
值添加完畢
double 後
increment 後
filter 後
filter 前
increment 前
double 前
i 的值是:6
值添加完畢
double 後
increment 後
filter 後
4
4
6
==================== 
foo3 前
foo2 前
foo1
foo2 後
foo3 後
由輸出結果可知特質的堆疊是從最右側的特質開始的
32.樣本類
case class Foo(i:Int)
scala 編譯器會自動爲樣例類添加一些便捷設定:
1)自動添加與類名一致的工廠方法,因此能夠用 Foo(1) 來建立Foo 對象
2)樣例類的參數列表裏的參數隱式添加了 val,這些參數會做爲樣例類的屬性存在
3)編譯器爲樣例類添加了 toString,hashCode和equal 的「天然」實現
 
33.封閉類
一旦你寫了模式匹配,就得保證考慮到了全部可能的狀況,不然程序就會報錯,scala 提供了一種檢查機制,能夠將超類封閉起來,這樣在編譯時scala 會自動檢查全部的匹配可能,可是,你必須把全部子類定義在存放超類的文件中,並在超類前加上 sealed,以下
 
package com.program
sealed abstract class Animal
case class Fish(sound:String) extends Animal
case class Bird(sound:String) extends Animal
case class Horse(sound:String) extends Animal
 
object Sealtest {
  def main(args: Array[String]): Unit = {
    val animal:Animal = Fish("gulu")
    val sound = animal match {
      case Fish(x) => x
    }
  }
}
如上代碼編譯時會有以下提示:
 
Warning:(10, 17) match may not be exhaustive.
It would fail on the following inputs: Bird(_), Horse(_)
    val sound = animal match {
若是不但願編譯器進行檢查,能夠加上(animal:@unchecked)match  ,實測很差用,scala 沒法識別(sclaal 版本2.11.8)
 
  val list = List(1, 2, 3)
    list match {
      case e@List(_*) => println(e) //List(1, 2, 3)  能把e所表明的變量取到
    }

 

 
34.list 類
 
package com.program
 
object ListSuite {
  //插入排序,xs 已是排序的
  def insert(x: Int, xs: List[Int]): List[Int] = {
    if (xs == Nil || x < xs.head) {
      x :: xs
    } else {
      xs.head :: insert(x, xs.tail)
    }
  }
 
  //對list 排序,list 的元素是無序的
  def isort(xs: List[Int]): List[Int] = xs match {
    case Nil => Nil
    case head :: tail => insert(head, isort(tail))
  }
 
  def main(args: Array[String]): Unit = {
    //插入排序
    var list = List(2)
    list = insert(1, list)
    list = insert(3, list)
    list = insert(4, list)
    list = insert(5, list)
    println(list) //List(1, 2, 3, 4, 5)
    //插入排序
 
    //隨機列表排序
    val list2 = List(3, 4, 1, 2, 6)
    println(isort(list2)) //List(1, 2, 3, 4, 6)
    //隨機列表排序
    //列表模式
    val listFruit = List("apple", "banana", "orange")
    val List(apple, banana, orange) = listFruit
    println(apple) // apple
    val x :: rest = listFruit
    println(x) // apple
    //列表模式
 
    //llist 一階方法
    //列表拼接
    val listconcat = list ::: list2 //List(1, 2, 3, 4, 5, 3, 4, 1, 2, 6)
    //獲取列表的長度,會遍歷列表的每個元素,耗時,若是隻需得知列表是否爲空,能夠調用listconcat.isEmpty
    listconcat.length
 
    //列表反轉
    println(list.reverse) //List(5, 4, 3, 2, 1)
    println(list.take(2)) //List(1, 2)
    println(list.drop(2)) //List(3, 4, 5)
    println(list.splitAt(2)) //(List(1, 2),List(3, 4, 5))
 
    println(list(2)) //獲取list 的index 爲2的元素,等價於 list.drop(2).head,因此比較耗時
    println(list.indices) //Range(0, 1, 2, 3, 4)  索引值組成的列表
 
    println(list.zip(list2)) //List((1,3), (2,4), (3,1), (4,2), (5,6))
    println(list.zipAll(9 :: list2, 2, 3)) //List((1,9), (2,3), (3,4), (4,1), (5,2), (2,6))
 
    println((list.zip(list2)).unzip) //(List(1, 2, 3, 4, 5),List(3, 4, 1, 2, 6))
 
    println(list.partition(_ % 2 == 0)) //(List(2, 4),List(1, 3, 5))
 
    println(list.find(_ % 2 != 0)) //返回第一個知足條件的元素
 
    println(list.takeWhile(_ % 2 != 0)) //List(1) 返回知足條件的最長序列
    println(list.dropWhile(_ % 2 != 0)) // List(2, 3, 4, 5)
    println(list.span(_ % 2 != 0)) // (List(1),List(2, 3, 4, 5))  takeWhile and dropWhile 的組合
 
    println(list.exists(_ % 2 == 0)) //true
    println(list.forall(_ % 2 != 0)) //false
 
    val max = (0 /: list) ((x, y) => if (x > y) x else y)
    println(max) //5
 
    val min = (list :\ 0) ((x, y) => if (x < y) x else y)
    println(min) //0
 
    println(List.fill(5)("a")) //List(a, a, a, a, a)
    
  }
}
 
 
 
35.泛型,上界,下界,協變,逆變
 
37 若是想在列表尾部追加元素,可使用高效的listBuffer,使用listBuffer 還能夠避免堆棧溢出
 
val lb = new ListBuffer[Int]
lb += 1
lb += 2
println(lb) //ListBuffer(1, 2)
 
38.若是須要可變長的數組,可使用ArrayBuffer,除了與array相同的操做外,還增長了首位添加,刪除操做
 
val ab = new ArrayBuffer[Int](10)
ab += 1
ab += 2
ab.remove(0) // 1 有返回值
39.若是須要先進先出的序列,可使用queue,queue分爲兩種,一種是可變隊列,一種是不可變隊列
 
 
val que = Queue(0)  不可變
val que2 = que.enqueue(1)
val que3 = que2.enqueue(List(2,3,4))
println(que3) //Queue(0, 1, 2, 3, 4)
println(que3.dequeue) //(0,Queue(1, 2, 3, 4))
 
val mque = collection.mutable.Queue(0)
mque += 1
mque += 2
println(mque) //Queue(0, 1, 2)
println(mque.dequeue()) //0
 
 
40.若須要先進後出的序列,可使用stack,stack 也有可變和不可變的
 
val stack = collection.mutable.Stack(0)
stack.push(1)
stack.push(2)
println(stack) //Stack(2, 1, 0)
println(stack.top)//2
println(stack.pop())//2
println(stack)//Stack(1, 0)
 
41.set 基本操做
 
var set = Set(1,2)
set += 5
set -= 1
set ++= List(3,4,5)
set --= List(2,3)
println(set)
println(set.intersect(Set(5,6))) //交集
 
42.map的基本操做
 
val map = collection.mutable.Map.empty[String, Int]
map += "a" -> 2
map += "a" -> 2
map += "a" -> 2
map("b") = 3
map ++= List("c" -> 3, "d" -> 4)
map --= List("a", "b")
println(map.keys) //iterator
println(map.values) //iterator
println(map.keySet) //set
println(map)
可變map 和不可變map的相互轉換 
 
scala.collection.mutable.HashMap.empty[Int, Int] ++ Map(1 -> 1)
Map.empty[Int, Int] ++ collection.mutable.HashMap(1 -> 1)
 
43.默認的集和映射
scala.collection.mutable.Set  工廠方法默認返回: scala.collection.mutable.HashSet
scala.collection.mutable.Map  工廠方法默認返回: scala.collection.mutable.HashMap
 
不可變集合的工廠方法返回對象比較複雜;
set
map
 
44.將類的主構造器設置爲私有的
將沒法經過主構造器建立實例,可是若是有輔助構造器,依然可使用輔助構造器建立實例
 
class Queue[T] private (val lead: List[T], val tail: List[T])
45.信息隱藏,不向用戶暴漏代碼實現細節
方案一:
class Foo private(val a:Int,val b:Int)
object Foo{
def apply(a:Int,b:Int) = new Foo(a,b)
}
 
方案二:
trait Foo{
val a:Int
val b:Int
}
 
object Foo{
def apply(...) = new FooSub(...)
private class FooSub extends Foo{
....
}
}
 
推薦使用方法二
 
46.爲何要用type
理由之一:提供一個類型的別名,能夠避免冗長的類型名字
 
47.一個例子
package com.program
 
class AbstractTest() extends Ft {
  val a = 3
}
 
 
trait Ft {
  val a: Int
  require(a > 0)
}
 
object AbstractTest {
  def main(args: Array[String]): Unit = {
    println(new AbstractTest().a)
  }
}
 
Exception in thread "main" java.lang.IllegalArgumentException: requirement failed
    at scala.Predef$.require(Predef.scala:212)
    at com.program.Ft$class.$init$(AbstractTest.scala:10)
    at com.program.AbstractTest.<init>(AbstractTest.scala:3)
    at com.program.AbstractTest$.main(AbstractTest.scala:15)
    at com.program.AbstractTest.main(AbstractTest.scala)
 
運行爲什麼回報錯,由於 AbstractTest 在初始化以前,先要初始化父類,此時val a 還未被初始化,因此報錯
改爲下面的寫法就能夠了
class AbstractTest(val a: Int) extends Ft {
 
}
 
48.枚舉簡單使用
package com.program
 
object WeekDay extends Enumeration {
  type WeekDay = Value
  val Mon = Value("1")
  val Tue = Value("2")
  val Wed = Value("3")
  val THu = Value("4")
  val Fri = Value("5")
  val Sat = Value("6")
  val Sun = Value("7")
 
  def checkExists(day: String): Boolean = {
    this.values.exists(_.toString == day)
  }
 
  def isWorkDay(day: WeekDay): Boolean = {
    !(day == Sat || day == Sun)
  }
 
  def showAll = this.values.foreach(println)
}
 
object EnumTest {
  def main(args: Array[String]): Unit = {
    println(WeekDay.checkExists("8"))
    println(WeekDay.Sun == WeekDay.withName("7"))
    println(WeekDay.Sun == 7)
    WeekDay.showAll
    println(WeekDay.isWorkDay(WeekDay.Sat))
  }
}
49.scala and xml
package com.program
 
import scala.xml.dtd.DocType
 
object XMLTest {
  def main(args: Array[String]): Unit = {
    //xml 字面量
    val hw = <a>
      {"hello" + ", world"}
    </a>
    println(hw)
    val num = 100 //<a>hello, world</a>
 
    val node = <a>{if (num > 100) <num>{num}</num> else xml.NodeSeq.Empty}</a>
    println(node) //<a></a>
 
 
    //推薦使用xml字面量,請看下面兩個例子
    println(<a>
      {"</a>可能存在危險"}
    </a>)
    //若使用低級字符串,則容易形成相似sql注入的結果
    println("<a>" + "</a>可能存在危險" + "</a>")
 
    //xml 序列化
    val stu = new Student {
      override val name: String = "jason"
      override val tel: String = "1345"
      override val addr: String = "sh"
      override val age: Int = 27
    }
    val stuXml = stu.toXml
    println(stuXml)
    /*<student>
      <name>jason</name>
      <age>27</age>
      <addr>sh</addr>
      <tel>1345</tel>
    </student>*/
 
    //若是想在xml文本中包含 {} 則能夠用{} 轉義
    val x = 23
    println(<a>{{{x}}}</a>) //<a>{23}</a>
 
    //xml 拆解
    val n3 = <a namea="na">a<b nameb="nb">b<c>c</c></b></a>
    println(n3.text) //abc
    println(n3 \ "b") //<b>b<c>c</c></b>
    println((n3 \ "b").text) //bc
    println(n3 \ "c") // "" 空字符串
    println(n3 \\ "c") //<c>c</c>    兩個斜槓表明深度搜索
    println(n3 \\ "@nameb") // nb 獲取標籤的屬性
 
    //xml 反序列化
    val stu2 = stu.fromXml(stuXml)
    println(stu2)
 
    //xml 的存儲與加載
    xml.XML.save("stu.xml", stuXml, "utf-8", true, null)
    xml.XML.loadFile("stu.xml")
 
    //xml 與模式匹配
    def proc(node: xml.Node): String = node match {
      case <a>{contents}</a> => s"it is an a : ${contents}"
      case <b>{contents}</b> => s"it is a b : ${contents}"
      case _ => s"it is something else"
    }
 
    println(proc(<a>apple</a>)) //it is an a : apple
    //proc 目前只能進行單個子節點的匹配 ,若是要匹配出如下內容,能夠用proc2方法
    println(proc(<b>a<em>yellow</em>banana</b>))//it is something else
    println(proc(<o>orange</o>))//it is something else
 
    def proc2(node:xml.Node):String = node match {
      case <b>{contents @ _*}</b> => s"it is b ${contents}"
      case _ => s"it is something else"
    }
 
    println(proc2(<b>a<em>yellow</em>banana</b>))//it is b ArrayBuffer(a, <em>yellow</em>, banana)
 
    //模式匹配與for
 
    val n4 =
      <students>
        <student>
          <name>jason</name>
          <age>25</age>
          <addr>sh</addr>
          <tel>123</tel>
        </student>
      </students>
    println("=================")
    n4 match {
      case <students>{students @_*}</students> =>
        for(student <- students){
          println((student \ "name").text)
        }
      case _ => println("nothing")
    }
    println("=================")
    /*=================
 
    jason
 
    =================*/
    println("<<<<<<<<<<>>>>>>>>>")
    n4 match {
      case <students>{students @_*}</students> =>
        for(student @ <student>{_*}</student> <- students){
          println((student \ "name").text)
        }
      case _ => println("nothing")
    }
    println("<<<<<<<<<<>>>>>>>>>")
    //<student>{_*}</student> 限制了for 表達式的枚舉
    /*<<<<<<<<<<>>>>>>>>>
    jason
    <<<<<<<<<<>>>>>>>>>*/
  }
}
 
abstract class Student {
  val name: String
  val age: Int
  val addr: String
  val tel: String
 
  def toXml =
    <student>
      <name>{name}</name>
      <age>{age}</age>
      <addr>{addr}</addr>
      <tel>{tel}</tel>
    </student>
 
 
  def fromXml(node: xml.Node): Student = {
    new Student {
      override val name: String = (node \ "name").text.trim
      override val tel: String = (node \ "tel").text.trim
      override val addr: String = (node \ "addr").text.trim
      override val age: Int = (node \ "age").text.trim.toInt
    }
  }
 
  override def toString = s"Student($name, $age, $addr, $tel)"
}
 
50.scala 中的equals 方法,最好與hashcode 一塊兒重寫
class Foo11(final val x: Int, final val y: Int) {
 
  override def hashCode(): Int = Objects.hash(new Integer(x), new Integer(y))
 
  override def equals(obj: scala.Any): Boolean = obj match {
    case that: Foo11 => (that canEqual (this)) && that.x == this.x && that.y == this.y
    case other => false
  }
 
  def canEqual(other: Any): Boolean = other.isInstanceOf[Foo11]
}
 
class Goo11(x: Int, y: Int, val z: Int) extends Foo11(x, y) {
 
  override def hashCode(): Int = super.hashCode() + Objects.hash(new Integer(z))
 
  override def equals(obj: Any): Boolean = obj match {
    case that: Goo11 => (that canEqual this) && super.equals(that) && that.z == that.z
    case other => false
  }
 
  override def canEqual(other: Any): Boolean = other.isInstanceOf[Goo11]
}
 
51.akka
 52.Option 的一些用法
    val mapx = Map("name" -> "jason", "age" -> "?")
    val s: String = null
    val a = Option(s).orElse(mapx.get("name")).orNull
    println(a) //jason
    println(Option("TOM").map(_.toLowerCase)) //Some(tom)
相關文章
相關標籤/搜索