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)