scala學(xué)習(xí)筆記2之lang下篇

22.13.main方法

Scala的main方法(類似java的static方法)必須定義在一個object內(nèi):object Test1 {?def main(args: Array[String]){println("hello world")}}

2.13.1.Application

不帶命令行參數(shù)的簡化main方法:object app1 extends Application{?println("hello world")}

2.14.package, import

2.14.1.import

Scala的import可以只在局部作用域內(nèi)生效鹿寨;“import javax.swing.{JFrame=>jf}”來聲明類型的別名掉蔬。jf.show() ? limport javax.swing._ ? ?import java.util.{List, Map} ??import java.util._, java.io._ ? ? ? ? ??Scala缺省導(dǎo)入如下包:?java.lang.* ??scala.* ??scala.Predef

由于Scala的package可以是相對路徑下定義浑厚,有可能命名沖突,可以用:import _root_.java.lang.Long

2.14.2.package

package com.wr3 {?//import java.nio._ // "*"是scala的正常函數(shù)名颜曾,所以用_

class c1 {?def m1() { println("c1.m1()") }?} ? ?object o1 {?def main(args: Array[String]) { ?println("o1.main()")?new c1().m1() ?}?}?}

編譯:fsc package.scala?運(yùn)行:java com.wr3.o1 //方式1 ? ? ??scala com.wr3.o1 //方式2

2.14.3.包對象

Scala2.8+支持包對象(package object),除了和2.8之前一樣可以有下級的object和class秉剑,還可以直接有下級變量和函數(shù)泛豪,例如:package p0 ?package object p1{?val a = 10 ? def b = "hello " + a?def main(args:Array[String]):Unit = printf("%s",p0.p1.b)?}

p1就是一個包對象,a和b就是包p1直屬的常量和函數(shù), ?$fsc foo.scala命令產(chǎn)生如下class:?./p0/p1/package.class ??調(diào)用:?scala p0.p1.package

2.15.if..else??

沒有java的:?b = (x>y) ? 100 : -1 ? ?就用:?if (x>y) 100 else -1 沒有Java的三元表達(dá)式

2.16.循環(huán)操作

map ?m->m ; ?flatMap?m->n ; ? indices ?m->m; ?foreach?m->Unit;?for (... if ...) ?yield ?m->n; ? ? ? ??collect ?{ case ... if ... => ... } ?m->n; ??filter, filterNot ?m->n;?take ?m->n;?takeWhile?m->n; ? ? ? ? ? ? forall ??m->1 (true|false);?reduceLeft, foldLeft?m->1;?scanLeft?m->m+1;?exists?m->1 (true|false); ??find?m->1 (或者None);?count?m->1;?span, partition?m->2.

2.16.1.for

循環(huán)中的變量不用定義侦鹏,如:

for(i<-1 to 10;j=i*i) println(j) ? ?for (s <- ss) foo(s) ? ?for (i <- 0 to n) foo(i) //包含n诡曙,即Range(0,1,2,...,n,n+1) ??for (i <- 0 until n) foo(i)? //不包含n,即Range(0,1,2,3,...,n) ??例如:?for(n<-List(1,2,3,4) if n%2?== 1) yield n*n? // List(1, 9) ?等價于不用for的寫法: ?List(1,2,3,4).filter(_%2?== 1).map(n => n*n) ?for ( n<-Array(1,2,3,4) if n%2?== 1) yield n*n? // Array(1, 9)注意:如果if后面不止一條語句略水,要用{..}包裹价卤。?var s = 0; for (i <- 0 until 100) { s += i } // s = 4950

for條件語句即可用(),也可用{}?如果條件是多行,不能用(),要用{}

for(i<-0 to 5; j<-0 to2) yield i+j?// Vector(0, 1,2,1,2, 3,2, 3, 4,3, 4, 5,4, 5, 6,5, 6, 7)

for{i<-0 to 5?j<-0 to2} ?yield i+j

例子1:?//邊長21以內(nèi)所有符合勾股弦的三角形:

def?triangle(n: Int) =for{ ? x <- 1 to21 ? y <- x to21 ? z <- y to21ifx * x + y * y == z * z }yield(x, y, z)

結(jié)果:// Vector((3,4,5), (5,12,13), (6,8,10), (8,15,17), (9,12,15), (12,16,20))

2.16.1.for .. yield

把每次循環(huán)的結(jié)果“移”進(jìn)一個集合(類型和循環(huán)內(nèi)的一致)?for {子句} yield {循環(huán)體}

正確:?for (e<-List(1,2,3)) yield (e*e) // List(1,4,9)?for {e<-List(1,2,3)} yield { e*e } // List(1,4,9) ? ??for {e<-List(1,2,3)} yield e*e // List(1,4,9)

錯誤:for (e<-List(1,2,3)) { yield e*e } //語法錯誤,yield不能在任何括號內(nèi)

2.16.2.foreach

List(1,2,3).foreach(println) ; (1to3).foreach(println); (1until4) foreach println;?Range(1,3) foreach println?注意:to包含聚请,until不包含(最后的數(shù))都可以寫步長荠雕,如:

1 to (11,2) // 1,3,5,7,9,11步長為2 ??== 1 to 11 by?2?

1 until (11,2) // 1,3,5,7,9 ?== 1 until 11 by?2

val r = (1 to 10 by 4) // (1,5,9), r.start=r.first=1; r.end=10, r.last=9

也可以是BigInt?(1:BigInt) to 3

2.16.3.forall

"所有都符合"——相當(dāng)于A1 && A2&& A3 && ... && Ai && ... && An

(1 to 3) forall (0<) // true ? ?(-1 to 3) forall (0<) // false

又如:def isPrime(n:Int) =2?until n forall (n % _ !=0)

for (i<-1 to 100 if isPrime(i)) println(i)

(2?to?20) partition (isPrime _)// (2,3,5,7,11,13,17,19), (4,6,8,9,10,12,14,15,16,18,20)

也可直接調(diào)用BigInt的內(nèi)部方法:

(2to20) partition (BigInt(_) isProbablePrime(10))

//注:isProbablePrime(c)中c越大,是質(zhì)數(shù)的概率越高驶赏,10對應(yīng)概率:1 - 1/(2**10) = 0.999

2.16.4.reduceLeft

reduceLeft方法首先應(yīng)用于前兩個元素炸卑,然后再應(yīng)用于第一次應(yīng)用的結(jié)果和接下去的一個元素,等等煤傍,直至整個列表盖文。例如?計(jì)算階乘:?deffac(n: Int) = 1 to n reduceLeft(_*_) ?fac(5) // 5*4*3*2= 120?相當(dāng)于:?((((1*2)*3)*4)*5)?

計(jì)算sum:List(2,4,6).reduceLeft(_+_) // 12?相當(dāng)于:?((2+4)+6)

取max:List(1,4,9,6,7).reduceLeft( (x,y)=> if (x>y) x else y ) // 9

或者簡化為:List(1,4,9,6,7).reduceLeft(_max_) // 9

相當(dāng)于:((((1 max 4) max 9) max 6) max 7)

2.16.5.foldLeft scanLeft

累加或累乘

def sum(L: List[Int]): Int = {?var result = 0?for (item <- L)?result += item?result?}

更scalable的寫法:

def sum(L: Seq[Int]) = L.foldLeft(0)((a, b) => a + b)

def sum(L: Seq[Int]) = L.foldLeft(0)(_ + _)

def sum(L: List[Int]) = (0/:L){_ + _}//暫時還不理解的請看2.16.6的注釋

調(diào)用:sum(List(1,3,5,7)) // 16

乘法:?def multiply(L: Seq[Int]) = L.foldLeft(1)(_ * _) ?multiply(Seq(1,2,3,4,5)) // 120?multiply(1 until 5+1) // 120

2.16.6.scanLeft

List(1,2,3,4,5).scanLeft(0)(_+_) // (0,1,3,6,10,15)?相當(dāng)于:(0,(0+1),(0+1+2),(0+1+2+3),(0+1+2+3+4),(0+1+2+3+4+5)) ?

List(1,2,3,4,5).scanLeft(1)(_*_) // (1,2,6,24,120)?相當(dāng)于?(1, 1*1, 1*1*2, 1*1*2*3, 1*1*2*3*4, 1*1*2*3*4*5)

注:(z/:List(a, b, c))(op)相當(dāng)于op(op(op(z, a), b), c) ?加法用0,乘法用1 ?(List(a, b, c):\z) (op) equals op(a, op(b, op(c,z))) ?注意兩者之間的差異 /: ?參數(shù)在左 ? ?:\參數(shù)在右 ?/:和:\的用法

2.16.7.take drop splitAt

1 to 10 by?2?take 3 // Range(1, 3, 5) ??1 to 10 by?2?drop 3 // Range(7, 9) ?1 to 10 by?2?splitAt?2// (Range(1, 3),Range(5, 7, 9))

例子:前10個質(zhì)數(shù)?def prime(n:Int) = (! ((2to math.sqrt(n).toInt) exists (i=> n%i==0)))

2?to 100 filter prime take 10

2.16.8.takeWhile, dropWhile, span

while語句的縮寫蚯姆, ?takeWhile(...)?等價于:while(...) {take}

dropWhile(...)?等價于:while(...) {drop}

span (...)?等價于:while (...) { take; drop }

1 to 10 takeWhile (_<5) // (1,2,3,4)

1 to 10 takeWhile (_>5) // () ?//Takes longest?prefix?of elements that satisfy a predicate.

10 to (1,-1) takeWhile(_>6) // (10,9,8,7)

1 to 10 takeWhile (n=>n*n<25) // (1,2, 3, 4)

如果不想直接用集合元素做條件五续,可以定義var變量來判斷:

例如洒敏,從1 to 10取前幾個數(shù)字,要求累加不超過30:

var sum=0; ?val rt = (1 to 10).takeWhile(e=> {sum=sum+e;sum<30})// Range(1,2, 3, 4, 5, 6, 7)

注意:takeWhile中的函數(shù)要返回Boolean疙驾,sum<30要放在最后凶伙;

1 to 10 dropWhile (_<5) // (5,6,7,8,9,10)

1 to 10 dropWhile (n=>n*n<25) // (5,6,7,8,9,10)

1 to 10 span (_<5) // ((1,2,3,4),(5,6,7,8,9它碎,10) )

List(1,0,1,0) span (_>0) // ((1), (0,1,0))

注意函荣,partition是和span完全不同的操作

List(1,0,1,0) partition (_>0) // ((1,1),(0,0))

2.16.9.break、continue

Scala中沒有break和continue語法扳肛!需要break得加輔助boolean變量傻挂,或者用庫(continue沒有).

例子1:打印'a' to 'z'的前10個?vari=0; val rt = for(e<-('a' to 'z') if {i=i+1;i<=10}) printf("%d:%s\n",i,e)

或者:('a' to 'z').slice(0,10).foreach(println)

例子2:1 to 100和小于1000的數(shù)

var (n,sum)=(0,0); for(i<-0 to 100 if (sum+i<1000)) { n=i; sum+=i }?// n = 44, sum = 990

例子3:使用庫來實(shí)現(xiàn)break ?import?scala.util.control.Breaks._

for(e<-1 to 10) { val e2= e*e; if (e2>10)break; println(e) }

2.17.操作符重載

注意:其實(shí)Scala沒有操作符,更談不上操作符重載挖息;+-/*都是方法名金拒,如1+2其實(shí)是(1).+(2)

object operator {class complex(vali:Int,valj:Int) { // val是必須的

def +(c2: complex) = {new complex (i+c2.i, j+c2.j)}

override def toString() = { "(" + i + "," + j + ")" }}

def main(args:Array[String]) = {?val c1 = new complex(3, 10) ?val c2= new complex(5, 70)

printf("%s + %s = %s", c1, c2, c1+c2)?}}

編譯:fsc operator.scala ?運(yùn)行:java operator // (3,10) + (5,70) = (8,80)

2.18.系統(tǒng)定義scala._

scala._ 自動加載,只有發(fā)生類名沖突時才需要帶上scala.包名套腹。

scala.AnyValue?所有基本類型的根?Int,Char,Boolean,Double,Unit

scala.AnyRef?所有引用類型的根?相當(dāng)于java的java.lang.Object

scala.Null?所有引用類型的子類

scala.Nothing?所有全部類型的子類

scala.List?不可變的List?scala特色的不可變List

scala.Int?scala中可以用int作為別名?Double绪抛,F(xiàn)loat等類

2.19.implicit隱式轉(zhuǎn)換

用途:把一種object類型安全地自動轉(zhuǎn)換成另一種object類型;不改動已有class設(shè)計(jì)即可添加新的方法;

2.19.1.類型轉(zhuǎn)換 (用法一)

implicit def foo(s:String):Int = Integer.parseInt(s) //需要時把String->Int def add(a:Int, b:Int) = a+b ??add("100",8) // 108,先把"100"隱式轉(zhuǎn)換為100

2.19.2.例子:階乘n!

第一步:寫函數(shù)?def factorial(n: Int) = 1 to n reduceLeft(_*_)

第二步:定義"!"函數(shù)?class m1(n: Int) {?def ! =factorial(n)?}

implicit def m2(n:Int) = new m1(n) //隱式轉(zhuǎn)換,即在需要時把n轉(zhuǎn)換為new m1(n)

注意:上面可以用匿名類簡化為:implicit def m2(n:Int) =new { def ! = factorial(n) }

第三步:使用?val n = 100?printf("%d! = %s\n", n, (n!))? // n!相當(dāng)于new m1(n).!() ?println(10!)

2.19.3.例子:cout ?//Converting the receiver

import java.io._

class C1(p:PrintStream) {def << (a:Any) = {p.print(a) ?p.flush?p?}}

implicit def anyFuncName(p:PrintStream) = new C1(p)

val endl = '\n'?System.out<<"hello"<<" world"<

System.out has no '<<' function, implicitly convert it as C1 object and call the function '<<'

2.19.4.例子:定義?:

implicit def elvisOperator[T](alt: T) =new{

def ?:[A >: T](pred: A) = if( pred ==null) alt else pred?}

null ?: "" // "" ? ?"abc" ?: "" // "abc" ? ??10 ?: 0 // 10 ? ? ??(null ?: 0).asInstanceOf[Int] // 0

2.19.5.已有Object加新方法(用法二Converting the receiver)

object NewMethod{?//定義新方法join()

implicit def?foo1[T](list:List[T]) = new {?def?join(s:String) = list.mkString(s)?}//測試

def main(args:Array[String]) :Unit= {?Console println List(1,2,3,4,5).join(" - ")// " 1 -2- 3 - 4-5"}}

解釋:編譯器發(fā)現(xiàn)List沒有join(String)方法沉迹,就發(fā)查找代碼中有沒有定義在implicit def xx(List)內(nèi)的join(String)方法睦疫,如果有就調(diào)用這個。

為Int增加乘方操作:def pow(n:Int, m:Int):Int = if (m==0) 1 else n*pow(n,m-1)?implicit def foo(n:Int) = new {def **(m:Int) = pow(n,m)?} ? ??2**10 // 1024

例子2:定義如ruby的10.next

implicit def foo(n:Int) = new { def next = n+1 } ? ?10.next // 11

2.20.type做alias

相當(dāng)于C語言的類型定義typedef鞭呕,建立新的數(shù)據(jù)類型名(別名)蛤育;在一個函數(shù)中用到同名類時可以起不同的別名

例如:type JDate = java.util.Date ??type SDate = java.sql.Date

val d1 = new JDate()? //相當(dāng)于val d = new java.util.Date()

val d2= new SDate()? //相當(dāng)于val d = new java.sql.Date()

注意:type也可以做泛型

用法三?Implicit parameters,缺省參數(shù)

class PreferredPrompt(val preference: String)

object Greeter {?def greet(name: String)(implicit?prompt: PreferredPrompt ) {

println("Welcome, "+ name +". The system is ready.")?println(prompt.preference)?}}

implicit?val prompt = new PreferredPrompt("Yes, master> ")

scala> Greeter.greet("Joe")

Welcome, Joe. The system is ready.

Yes, master>

2.21.泛型

2.21.1.函數(shù)中的泛型:

def foo[T](a:T) = println("value is " + a) ?foo(10) // "value is 10"?foo(3.14) // "value is 3.14"?foo("hello") // "value is hello"

2.21.2.類中的泛型:

class C1[T] {?private var v:T = _ ??def set(v1:T) = { v = v1 }?def get = v?} ??new C1[Int].set(10).get // 10?new C1[String].set("hello").get // "hello"

2.21.3.泛型定義type

abstract?class C1 { ?type T?val e:T?}

abstract?class C2?{ ?type T?val list:List[T]?def len = list.length?}

def m1(e1:Int) = new C1{ ?type T = Int?val e = e1?}

def m2(e1:List[Int]) = new C2?{?type T = Int ?val list = e1?}

Console println m1(10) // 10

Console println m2(List(1,2,3,4,5)).len // 5

注意:type也可以做數(shù)據(jù)類型的alias;C語言中的typedef

2.22.枚舉Enum

Scala沒有在語言層面定義Enumeration葫松,而是在庫中實(shí)現(xiàn):

例子1:

object Color extends Enumeration{?type Color =Value?val RED, GREEN, BLUE, WHITE, BLACK =Value?}

注:有點(diǎn)費(fèi)解瓦糕,特別是Enumeration defines an inner class named Value

Color.RED // Color.Value = RED

import Color._

val colorful = Color.values filterNot (e=> e==WHITE || e==BLACK)

colorful foreach println // RED\nGREEN\nBLUE

例子2

object Color extends Enumeration {

val RED =Value("紅色")

val GREEN = Value("綠色")

val BLUE = Value("藍(lán)色")

val WHITE = Value("黑")

val BLASK = Value("白")

}

Color.RED // Color.Value =紅色

import Color._

val colorful = Color.values filterNot (List("黑","白") contains _.toString)

colorful foreach println //紅色\n綠色\n藍(lán)色

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市腋么,隨后出現(xiàn)的幾起案子咕娄,更是在濱河造成了極大的恐慌,老刑警劉巖珊擂,帶你破解...
    沈念sama閱讀 216,843評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件圣勒,死亡現(xiàn)場離奇詭異,居然都是意外死亡摧扇,警方通過查閱死者的電腦和手機(jī)圣贸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,538評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來扛稽,“玉大人吁峻,你說我怎么就攤上這事。” “怎么了用含?”我有些...
    開封第一講書人閱讀 163,187評論 0 353
  • 文/不壞的土叔 我叫張陵矮慕,是天一觀的道長。 經(jīng)常有香客問我啄骇,道長痴鳄,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,264評論 1 292
  • 正文 為了忘掉前任肠缔,我火速辦了婚禮夏跷,結(jié)果婚禮上哼转,老公的妹妹穿的比我還像新娘明未。我一直安慰自己,他們只是感情好壹蔓,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,289評論 6 390
  • 文/花漫 我一把揭開白布趟妥。 她就那樣靜靜地躺著,像睡著了一般佣蓉。 火紅的嫁衣襯著肌膚如雪披摄。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,231評論 1 299
  • 那天勇凭,我揣著相機(jī)與錄音疚膊,去河邊找鬼。 笑死虾标,一個胖子當(dāng)著我的面吹牛寓盗,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播璧函,決...
    沈念sama閱讀 40,116評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼傀蚌,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了蘸吓?” 一聲冷哼從身側(cè)響起善炫,我...
    開封第一講書人閱讀 38,945評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎库继,沒想到半個月后箩艺,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,367評論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡宪萄,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,581評論 2 333
  • 正文 我和宋清朗相戀三年艺谆,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片雨膨。...
    茶點(diǎn)故事閱讀 39,754評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡擂涛,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情撒妈,我是刑警寧澤恢暖,帶...
    沈念sama閱讀 35,458評論 5 344
  • 正文 年R本政府宣布,位于F島的核電站狰右,受9級特大地震影響杰捂,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜棋蚌,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,068評論 3 327
  • 文/蒙蒙 一嫁佳、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧谷暮,春花似錦蒿往、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,692評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至颊埃,卻和暖如春蔬充,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背班利。 一陣腳步聲響...
    開封第一講書人閱讀 32,842評論 1 269
  • 我被黑心中介騙來泰國打工饥漫, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人罗标。 一個月前我還...
    沈念sama閱讀 47,797評論 2 369
  • 正文 我出身青樓庸队,卻偏偏與公主長得像,于是被迫代替她去往敵國和親馒稍。 傳聞我的和親對象是個殘疾皇子皿哨,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,654評論 2 354

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