scala學(xué)習(xí)筆記之lang1

lang

2.1.和Java的異同

2.1.1.語法

Java++:增加的語法 -》純OO;操作符重載凌净;closure泻蚊;使用trait進(jìn)行mixin組合;existential type(_)没卸;抽象類型(type T) class C1[T]{...}秒旋;模式匹配 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??Java--:刪減的語法-》 靜態(tài)成員迁筛;原生數(shù)據(jù)類型;break尉桩、continue贪庙;接口止邮;通配符List, import pkg.*;;原始類型class C1<T> {...}屈扎;enum枚舉

注:existential type——和Java互操作時進(jìn)行對應(yīng),?Iterator? -->? Iterator[T] { type T <: Component }或者Iterator[_]

2.1.2.庫:以下功能通過庫的形式提供:assert,enum,property,event,actor,resource control(自動釋放),query

2.2.變量

2.2.1.保留字

abstract case catch class def?do else extends false final?finally for if implicit import?match new null object override?package private protected requires return?sealed super this throw trait?try true type val var while with yield??_ ? ? ?: ? ? = ? ? => ? ?<- ? ?<: ? <% ? ? ?>: ? ? ?# ? ? ? ?@ ?(弄清出這些符號的含義) ??Scala調(diào)用Java的方法時鹰晨,會碰到有Scala的保留字止毕,如Thread.yield();?這在Scala中是非法的滓技,專門有個解決辦法,寫成:Thread.`yield`() ??注意:沒有break和continue

2.2.2.變量標(biāo)識

這些標(biāo)識在Java中是非法的膝昆,在Scala中是合法的叠必,可以當(dāng)作函數(shù)名使用纬朝,使接口更加DSL:val empty_? = true ? ? ? ??val + = "hello" ? ? ? ? val `yield` = 10 ? ? ?val ** = "power" (經(jīng)常看不懂)?注意:可用但可讀性不好

2.2.3.變量定義

2.2.3.1val, var

var可變判没,可重新賦值,賦值為"_"表示缺省值(0, false, null)嫉沽,例如:var d:Double = _ // d = 0.0 绸硕;?var i:Int = _ // i = 0 ?; ?var s:String = _ // s = null ? ?; ??var t:T = _? //泛型T對應(yīng)的默認(rèn)值?注意:僅 var可用"_"表示缺省值賦值魂毁。 使用val _ 缺省 會在運(yùn)行時報錯:unbound placeholder parameter

val不可變,相當(dāng)于const/final咬崔,但如果val為數(shù)組或者List刁赦,val的元素可以賦值;val pi = 3. //相當(dāng)于3.0d ;?val pi = 3.f //相當(dāng)于3.0f?提示:向函數(shù)式風(fēng)格推進(jìn)的一個方式甚脉,就是嘗試不用任何var來定義變量铆农。

2.2.3.2花樣定義

和Python一樣方便的賦值方式:val x,y = 0 //賦同一初始值 ;val (x,y) = (10, "hello") //同時定義多個變量墩剖,注意:val x,y=10,"hello"是錯誤的 ;?val x::y = List(1,2,3,4)? // x = 1, y = List(2,3,4) ?val List(a,b,c) = List(1,2,3) // a = 1, b = 2, c = 3 ;?val Array(a,b,_, _,c@_*) = Array(1,2,3,?4,5,?6,?7)? //也可以用List,Seq ?a // 1 ?b // 2?c // Array(5, 6, 7), _*匹配0個到多個

使用正則表達(dá)式定義:val regex = "(\\d+)/(\\d+)/(\\d+)".r ?val regex(year, month, day) = "2010/1/13"?// year: String = 2010; ?// month: String = 1;// day: String = 13

2.2.3.3lazy, val, def的區(qū)別

val:定義時就一次求值完成,保持不變?val f = 10+20 // 30

lazy:定義時不求值,第一次使用時完成求值,保持不變?lazy f = 10+20 //?f // 30

def:定義時不求值,每次使用時都重新求值?(無參,缺省返回值類型的函數(shù)定義)def f = 10+20 // 30?def t = System.currentTimeMillis //每次不一樣

scala>val f1 = System.currentTimeMillis ?f1: Long = 1279682740376? ??//馬上求值 ?scala>f1 ?res94: Long = 1279682740376 //之后保持不變?scala>lazy val f2 = System.currentTimeMillis?f2: Long = ? //定義時不求值?scala>System.currentTimeMillis?res95: Long = 1279682764297?scala>f2?res96: Long = 1279682766545//第一次使用時求值郊霎,注意:6545 > 4297?scala>f2?res97: Long = 1279682766545//之后保持不變?scala>def f3 = System.currentTimeMillis?f3: Long?scala>f3 ?res98: Long = 1279682784478//每次求值?scala>f3?res99: Long = 1279682785352//每次求值

2.3.基本類型

盡量使用大寫形式:Int, Long, Double, Byte, Short, Char, Float, Double, Boolean,編譯時Scala自動對應(yīng)到Java原始類型书劝,提高運(yùn)行效率购对。Unit對應(yīng)java的void,用asInstanseOf[T]方法來強(qiáng)制轉(zhuǎn)換類型:def i = 10.asInstanceOf[Double] // i: Double = 10.0?List('A','B','C').map(c=>(c+32).asInstanceOf[Char]) // List('a','b','c') ?用isInstanceOf[T]方法來判斷類型:?val b = 10.isInstanceOf[Int] // true; ?而在match ... case中可以直接判斷而不用此方法陶因。

用Any統(tǒng)一了原生類型和引用類型。

Any統(tǒng)一原生類型和引用類型

2.3.1.Int

-3 abs // 3 ;?-3 max -2 // -2 ;?-3 min -2 // -3 ;1.4ound // 1四舍五入;?1.6 round // 2四舍五入;?1.1 ceil // 2.0 天花板?1.1 floor // 1.0地板?注:Rich Wrapper operations

無++贴见,--操作亚铁,但可以+=, -=,如下:var i = 0?i++ ?//報錯徘溢,無此操作; i+=1 // 1 ;?i--? //報錯捆探,無此操作;?i-=1 // 0 ?def even(n:Int) = 0==(n & 1) ?def odd(n:Int) = !even(n)

2.3.2.Char

String可以轉(zhuǎn)化為List[Char]?在String上做循環(huán)黍图,其實就是對String中的每一個Char做操作,如:?"jamesqiu" max // 'u'?"jamesqiu" min // 'a'?('a' to 'f') map (_.toString*3) // (aaa, bbb, ccc, ddd, eee, fff)

2.4.BigInt

可以表示很大的整數(shù):BigInt(10000000000000000000000000) //報錯; ?BigInt("10000000000000000000000000") // scala.math.BigInt = 10000000000000000000000000

例如:def? fac(n:Int):BigInt = if (n==0) 1 else fac(n-1)*n?fac(1000)?或者寫成:def fac2(n:Int) = ((1:BigInt) to n).product?// res1: BigInt = 9332621544394415268169923885626670049071596826438......000000000000000000

2.5.字符串

"..."或者"""...""""

println("""|Welcome?to?Ultamix?3000.

|Type?"HELP"?for?help.""".stripMargin)

輸出:

Welcome?to?Ultamix?3000.

Type?"HELP"?for?help.

scala中剖张,字符串除了可以+搔弄,也可以* ? ??"abc" * 3// "abcabcabc" ? ? ?"abc" * 0// "" ?例子: ?"google".reverse // "elgoog" ? ?"abc".reverse.reverse=="abc" // true ; ?"Hello" map (_.toUpper) //相當(dāng)于"Hello".toUpperCase

2.5.1.類型轉(zhuǎn)換

"101".toInt // 101丰滑,無需Integer.parseInt("101"); ??"3.14".toFloat // 3.14f ? ; ??101.toString ?; ?3.14.toString ? ; ? ?轉(zhuǎn)換整個列表:List("1","2","3") map (_.toInt) // List(1,2,3)?或者?List("1","2","3") map Integer.parseInt // List(1,2,3)

2.5.2.StringBuilder

val sb = new StringBuilder ??sb += 'H' ??sb ++= "ello" ?sb.toString // "Hello"?sb clear // ?StringBuilder()

2.5.3.文本格式化

使用java.text.MessageFormat.format:?val?msg = java.text.MessageFormat.format(?"At{1,time}on{1,date}, there was{2}on planet{0}.","Hoth",newjava.util.Date(),"a disturbance in the Force") ??輸出?At17:50:34on2010-7-20, there wasa disturbance in the Forceon planetHoth. ?方法2:?"my name is %s, age is %d."format("james", 30)//my name is james, age is 30.?注意:format還可以這么用?"%s-%d:%1$s is %2$d."format("james", 30)//james-30:james is 30. ??"%2$d age's man %1$s: %2$d"format("james", 30) //30 age's man james: 30

2.6.Null, None, Nil, Nothing

Null:?Trait褒墨,其唯一實例為null郁妈,是AnyRef的子類,*不是*AnyVal的子類

Nothing:?Trait顾彰,所有類型(包括AnyRef和AnyVal)的子類剧腻,沒有實例

None:Option的兩個子類之一书在,另一個是Some,用于安全的函數(shù)返回值

Unit:無返回值的函數(shù)的類型栏账,和java的void對應(yīng)

Nil:?長度為0的List

2.7.==和eq

Scala的==很智能,他知道對于數(shù)值類型要調(diào)用Java中的==竖般,ref類型要調(diào)用Java的equals() ?"hello"=="Hello".toLowerCase() ?在java中為false茶鹃,在scala中為true ;?Scala的==總是內(nèi)容對比基本類型Int闭翩,Double,比值,?其他類型?相當(dāng)于A.equals(B) ? ?eq才是引用對比

例如:val s1,s2 = "hello" ?val s3 = new String("hello") ?s1==s2 // true ??s1 eq s2 // true ??s1==s3 // true值相同 ?s1 eq s3 // false不是同一個引用

2.8.Option[T]

2.8.1.概念

Option[T]可以是任意類型或者空兑障,但一旦聲明類型就不能改變蕉汪;Option[T]可完美替代Java中的null者疤,可以是Some[T]或者None;Option實現(xiàn)了map, flatMap, and filter接口竞漾,允許在'for'循環(huán)里使用它窥翩;

函數(shù)返回值能被統(tǒng)一處理了:

沒有Option的日子 def find(id:Long):Person = ...? 返回Person或者null? 返回null不特殊處理會拋:NullPointerExceptions? 類比:Java的Stringx.split返回null

現(xiàn)在:?def find(id:Long):Option[Person] = ...?返回Some[Person]或者None?返回值直接getOrElse或者列表操作?類比:Java的Stringx.split返回new String[0]

結(jié)論:函數(shù)永遠(yuǎn)不要返回null值寇蚊,如果輸入有問題或者拋異常,返回Option[T]

參數(shù)有效性檢查沒有那么煩人了:沒有Option的日子: def blank(s:String) =if (s==null) false else{s.toList.forall(_.isWhitespace) } ??現(xiàn)在:?def blank(s:String) =Option(s).toList.forall(_.forall(_.isWhitespace))?結(jié)論:盡可能地不要浪費(fèi)代碼去檢測輸入允耿,包裝成Option[T]來統(tǒng)一處理

2.8.2.使用

Some(3).getOrElse(4) // 3 ? ?None.getOrElse(4) // 4 ? ?打印key=3的value:寫法1:def p(map:Map[Int,Int]) = println(map(3))?p(Map(1->100,2->200)) //拋異常?寫法2:def p(map:Map[Int,Int]) = println(map get 3 getOrElse "...") ?p(Map(1->100,2->200)) // ... ? ?p(Map(1->100,3->300)) // 300

2.8.3.例子

例子1:defm(k:Int) = {Map((1,100),(2,200),(3,300)) get(k) match {?case Some(v) =>?k+": "+v ?case None =>?"not found"?}}

def main(args:Array[String]) :Unit= {?println(m(1)) // 100 ??println(m(2)) // 200 ??println(m(3)) // 300 ?println(m(4)) // "not found"?println(m(-1)) // "not found"?}

例子2:val l = List(Some(100),None, Some(200), Some(120),None) ?for (Some(s) <- l) yields// List(100, 200, 120) ?或 ?l?flatMap (x=>x)// List(100, 200, 120)

例子3:Option結(jié)合flatMap?def toint(s:String) =?try { Some(Integer.parseInt(s)) } catch { case e:Exception => None } ?List("123", "12a", "45") flatMap toint // List(123, 45) ?List("123", "12a", "45") map toint // List(Some(123), None, Some(45))

2.9.區(qū)分<-,=>,->

<- ? ??for (i <- 0 until 100) ??用于for循環(huán),符號∈的象形

=> ? ??List(1,2,3).map(x=> x*x) ??((i:Int)=>i*i)(5) // 25 ? ? ?用于匿名函數(shù) ?也可用在import中定義別名:import javax.swing.{JFrame=>jf}

->?Map(1->"a",2->"b")?用于Map初始化,也可以不用->而寫成Map((1,"a"),(2,"b"))

2.10.match..case(switch)

2.10.1.和switch..case的區(qū)別

Java里面的寫法:switch(n) {?case(1): ...; break;?case(2): ...; break;?default: ...;?} ? ? ? ? ? ? ? ? ? ? ? Scala寫法:def m(n:String) =?n match {?case "a"|"b"=>... //這個比較好 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?case "c" =>...?case _ =>...?}?匹配值每個case..=>結(jié)束不用寫break了,_相當(dāng)于default

2.10.2.匹配數(shù)據(jù)類型

match可以很簡單地匹配數(shù)據(jù)類型(不需要isInstanceOf[T]):def f(v:Any) = v match {case null => "null" ?case i:Int => i*100?case s:String => s ?case _ => "others"?}?注意:上面case中的i蚂蕴、s都叫模式變量 ??f(null) // "null" ? ?f(5) // 500 ??f("hello") // "hello" ??f(3.14) // "others" ?注意:自定義類型如果也要匹配骡楼,需要用case class

2.10.3.命令行參數(shù)解析例子

/** Basic command line parsing. */

object?Main { ?var?verbose =?false?//記錄標(biāo)識,以便能同時對-h和-v做出響應(yīng)

def?main(args: Array[String]) {

for(a <- args) ?a?match{?case"-h"|"-help"=>?println("Usage: scala Main [-help|-verbose]")

case"-v"|"-verbose"=> ?verbose =true

case?x?=>?//這里x是臨時變量 ??println("Unknown option: '"+ x +"'")?}

if(verbose) println("How are you today?") ?}?}

2.10.4.使用case的遞歸函數(shù)

寫法1:def fac(n:Int):Int = n match { ?case 0=>1 ??case _=>n*fac(n-1) ?}

寫法2(使用映射式函數(shù)):def fac: Int=>Int = {?case 0=> 1 ? ?case n=> n*fac(n-1) ?}

寫法3(使用尾遞歸):def fac: (Int,Int)=>Int= {?case (0,y) =>y?case(x,y) =>fac(x-1,x*y)?}?fac(5,1) // 120

寫法4(reduceLeft):def fac(n:Int) = 1 to n reduceLeft(_*_)?implicit def foo(n:Int) = new { def ! = fac(n) } ??5!// 120

寫法5:(最簡潔高效)?def fac(n:Int) = (1:BigInt) to n product?fac(5) // 120

2.10.5.變量匹配

常量匹配很簡單引镊,即case后跟的都是常量弟头;

變量匹配需要注意兑燥,case后跟的是match里面的臨時變量降瞳,而不是其他變量名:

3 match {?case i => println("i=" + i) //這里i是模式變量(臨時變量)蚓胸,就是3?}

val a = 10?20 match { case a => 1 } // 1,a是模式變量扔枫,不是10

為了使用變量a短荐,必須用`a`:20 match { case`a`=> 1; case b => -1 } // -1叹哭,`a`是變量10?或者用大寫的變量val A = 10?20 match { case A=> 1; case b => -1 } // -1,大寫A是變量10

2.10.6.case..if條件匹配

寫法1:

(1 to 20) foreach {case?x?if(x % 15 == 0) => printf("%2d:15n\n",x)?case?x?if(x % 3 == 0) ?=> printf("%2d:3n\n",x)?case?x?if(x % 5 == 0) ?=> printf("%2d:5n\n",x)?case?x => printf("%2d\n",x) }

寫法2:

(1 to 20) map ( x => (x%3,x%5) match {?case(0,0)=> printf("%2d:15n\n",x) ?case(0,_)=> printf("%2d:3n\n",x) ?case(_,0)=> printf("%2d:5n\n",x)?case(_,_)=> printf("%2d\n",x)?})

2.11.try..catch..finally

var f = openFile()

try{?f = new FileReader("input.txt")?} catch {?case ex: FileNotFoundException => // Handle missing file?case ex: IOException => // Handle other I/O error ?} finally {?f.close()?}

2.12.require

def f(n:Int) = { require(n!=0); 1.0/n } ?def f(n:Int) = { require(n!=0, "n can't be zero"); 1.0/n }?f(0)

// java.lang.IllegalArgumentException: requirement failed:?n can't be zero

require method takes one boolean parameter. If the passed value is true, require will return normally, otherwise, require throu an IllegalArgumentException. require 內(nèi)含一個bool型參數(shù),如果返回為true入宦,則正常返回室琢;否則 拋出參數(shù)非法異常盈滴。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市宽菜,隨后出現(xiàn)的幾起案子铅乡,更是在濱河造成了極大的恐慌,老刑警劉巖花履,帶你破解...
    沈念sama閱讀 211,042評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件挚赊,死亡現(xiàn)場離奇詭異荠割,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)夺克,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評論 2 384
  • 文/潘曉璐 我一進(jìn)店門铺纽,熙熙樓的掌柜王于貴愁眉苦臉地迎上來哟忍,“玉大人锅很,你說我怎么就攤上這事〕①耍” “怎么了鹏控?”我有些...
    開封第一講書人閱讀 156,674評論 0 345
  • 文/不壞的土叔 我叫張陵当辐,是天一觀的道長。 經(jīng)常有香客問我耍群,道長,這世上最難降的妖魔是什么慷吊? 我笑而不...
    開封第一講書人閱讀 56,340評論 1 283
  • 正文 為了忘掉前任溉瓶,我火速辦了婚禮谤民,結(jié)果婚禮上张足,老公的妹妹穿的比我還像新娘。我一直安慰自己哼绑,他們只是感情好吵聪,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,404評論 5 384
  • 文/花漫 我一把揭開白布吟逝。 她就那樣靜靜地躺著赦肋,像睡著了一般佃乘。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上庞呕,一...
    開封第一講書人閱讀 49,749評論 1 289
  • 那天住练,我揣著相機(jī)與錄音愁拭,去河邊找鬼。 笑死盏混,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的止喷。 我是一名探鬼主播混聊,決...
    沈念sama閱讀 38,902評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼技羔,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了鳖粟?” 一聲冷哼從身側(cè)響起向图,我...
    開封第一講書人閱讀 37,662評論 0 266
  • 序言:老撾萬榮一對情侶失蹤标沪,失蹤者是張志新(化名)和其女友劉穎金句,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體贞瞒,經(jīng)...
    沈念sama閱讀 44,110評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡军浆,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年乒融,在試婚紗的時候發(fā)現(xiàn)自己被綠了摄悯。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,577評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖叨橱,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情愉舔,我是刑警寧澤轩缤,帶...
    沈念sama閱讀 34,258評論 4 328
  • 正文 年R本政府宣布火的,位于F島的核電站,受9級特大地震影響征椒,放射性物質(zhì)發(fā)生泄漏湃累。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,848評論 3 312
  • 文/蒙蒙 一蒙秒、第九天 我趴在偏房一處隱蔽的房頂上張望晕讲。 院中可真熱鬧榜田,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽具钥。三九已至,卻和暖如春掌动,著一層夾襖步出監(jiān)牢的瞬間四啰,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評論 1 264
  • 我被黑心中介騙來泰國打工粗恢, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留柑晒,地道東北人。 一個月前我還...
    沈念sama閱讀 46,271評論 2 360
  • 正文 我出身青樓眷射,卻偏偏與公主長得像匙赞,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子妖碉,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,452評論 2 348

推薦閱讀更多精彩內(nèi)容

  • Scala的集合類可以從三個維度進(jìn)行切分: 可變與不可變集合(Immutable and mutable coll...
    時待吾閱讀 5,807評論 0 4
  • FP 3.1.函數(shù) 函數(shù)的地位和一般的變量是同等的涌庭,可以作為函數(shù)的參數(shù)欧宜,可以作為返回值坐榆。傳入函數(shù)的任何輸入是只讀的...
    時待吾閱讀 1,105評論 0 2
  • 22.13.main方法 Scala的main方法(類似java的static方法)必須定義在一個object內(nèi):...
    時待吾閱讀 754評論 0 0
  • 數(shù)組是一種可變的、可索引的數(shù)據(jù)集合鱼鸠。在Scala中用Array[T]的形式來表示Java中的數(shù)組形式 T[]猛拴。 v...
    時待吾閱讀 948評論 0 0
  • 背景 一年多以前我在知乎上答了有關(guān)LeetCode的問題, 分享了一些自己做題目的經(jīng)驗。 張土汪:刷leetcod...
    土汪閱讀 12,737評論 0 33