您的位置:首页 > 其它

Scala的数据类型和基础语法

2014-10-16 11:48 716 查看
lang

2.1.和Java的异同

2.1.1.语法

Java++:增加的语法Java--:删减的语法
纯OO静态成员
操作符重载原生数据类型
closurebreak、continue
使用trait进行mixin组合接口
existentialtype(_)通配符List<?>,importpkg.*;
抽象类型(typeT)classC1[T]{...}原始类型classC1<T>{...}
模式匹配enum枚举
注:existentialtype——和Java互操作时进行对应Iterator<?extendsComponent>-->Iterator[T]{typeT<:Component}或者Iterator[_]

2.1.2.

以下功能通过库的形式提供:lassertlenumlpropertyleventlactorlresourcecontrol(自动释放)lquery

2.2.变量

2.2.1.保留字

abstractcasecatchclassdefdoelseextendsfalsefinalfinallyforifimplicitimportmatchnewnullobjectoverridepackageprivateprotectedrequiresreturnsealedsuperthisthrowtraittrytruetypevalvarwhilewithyield_:==><-<:<%>:#@Scala调用Java的方法时,会碰到有Scala的保留字,如Thread.yield()这在Scala中是非法的,专门有个解决办法,写成:Thread.`yield`()注意:没有break和continue

2.2.2.变量标识

这些标识在Java中是非法的,在Scala中是合法的,可以当作函数名使用,使接口更加DSL:valempty_?=trueval+="hello"val`yield`=10val**="power"注意:可用但可读性不好

2.2.3.变量定义

2.2.3.1val,var

var可变,可重新赋值,赋值为"_"表示缺省值(0,false,null),例如:vard:Double=_//d=0.0vari:Int=_//i=0vars:String=_//s=nullvart:T=_//泛型T对应的默认值注意:仅val可用"_"表示缺省值赋值。val不可变,相当于const/final,但如果val为数组或者List,val的元素可以赋值;valpi=3.//相当于3.0dvalpi=3.f//相当于3.0f提示:向函数式风格推进的一个方式,就是尝试不用任何var来定义变量。

2.2.3.2花样定义

和Python一样方便的赋值方式:valx,y=0//赋同一初始值val(x,y)=(10,"hello")//同时定义多个变量,注意:valx,y=10,"hello"是错误的更花:valx::y=List(1,2,3,4)//x=1,y=List(2,3,4)valList(a,b,c)=List(1,2,3)//a=1,b=2,c=3进一步花样:valArray(a,b,_,_,c@_*)=Array(1,2,3,4,5,6,7)//也可以用List,Seqa//1b//2c//Array(5,6,7),_*匹配0个到多个这个也太花了吧!使用正则表达式定义:valregex="(\\d+)/(\\d+)/(\\d+)".rvalregex(year,month,day)="2010/1/13"//year:String=2010//month:String=1//day:String=13

2.2.3.3lazy,val,def的区别

val定义时就一次求值完成,保持不变valf=10+20//30
lazy定义时不求值,第一次使用时完成求值,保持不变lazyf=10+20//<lazy>f//30
def定义时不求值,每次使用时都重新求值(无参,缺省返回值类型的函数定义)deff=10+20//30deft=System.currentTimeMillis//每次不一样
scala>valf1=System.currentTimeMillisf1:Long=1279682740376//马上求值scala>f1res94:Long=1279682740376//之后保持不变scala>lazyvalf2=System.currentTimeMillisf2:Long=<lazy>//定义时不求值scala>System.currentTimeMillisres95:Long=1279682764297scala>f2res96:Long=1279682766545//第一次使用时求值,注意:6545>4297scala>f2res97:Long=1279682766545//之后保持不变scala>deff3=System.currentTimeMillisf3:Longscala>f3res98:Long=1279682784478//每次求值scala>f3res99:Long=1279682785352//每次求值

2.3.基本类型

尽量使用大写形式:Int,Long,Double,Byte,Short,Char,Float,Double,Boolean编译时Scala自动对应到Java原始类型,提高运行效率。Unit对应java的void用asInstanseOf[T]方法来强制转换类型:defi=10.asInstanceOf[Double]//i:Double=10.0List('A','B','C').map(c=>(c+32).asInstanceOf[Char])//List('a','b','c')用isInstanceOf[T]方法来判断类型:valb=10.isInstanceOf[Int]//true而在match...case中可以直接判断而不用此方法。用Any统一了原生类型和引用类型。

2.3.1.Int

-3abs//3-3max-2//-2-3min-2//-31.4round//1四舍五入1.6round//2四舍五入1.1ceil//2.0天花板1.1floor//1.0地板注:RichWrapperoperations无++,--操作,但可以+=,-=,如下:vari=0i++//报错,无此操作i+=1//1i--//报错,无此操作i-=1//0defeven(n:Int)=0==(n&1)defodd(n:Int)=!even(n)

2.3.2.Char

String可以转化为List[Char]在String上做循环,其实就是对String中的每一个Char做操作,如:"jamesqiu"max//'u'"jamesqiu"min//'a'('a'to'f')map(_.toString*3)//(aaa,bbb,ccc,ddd,eee,fff)

2.4.BigInt

可以表示很大的整数:BigInt(10000000000000000000000000)//报错BigInt("10000000000000000000000000")//scala.math.BigInt=10000000000000000000000000例如:deffac(n:Int):BigInt=if(n==0)1elsefac(n-1)*nfac(1000)或者写成:deffac2(n:Int)=((1:BigInt)ton).product//res1:BigInt=9332621544394415268169923885626670049071596826438......000000000000000000

2.5.字符串

"..."或者"""...""""println("""|WelcometoUltamix3000.|Type"HELP"forhelp.""".stripMargin)输出:WelcometoUltamix3000.Type"HELP"forhelp.scala中,字符串除了可以+,也可以*"abc"*3//"abcabcabc""abc"*0//""例子:"google".reverse//"elgoog""abc".reverse.reverse=="abc"//true例子:"Hello"map(_.toUpper)//相当于"Hello".toUpperCase

2.5.1.类型转换

"101".toInt//101,无需Integer.parseInt("101");"3.14".toFloat//3.14f101.toString3.14.toString转换整个列表:List("1","2","3")map(_.toInt)//List(1,2,3)或者List("1","2","3")mapInteger.parseInt//List(1,2,3)

2.5.2.StringBuilder

valsb=newStringBuildersb+='H'sb++="ello"sb.toString//"Hello"sbclear//StringBuilder()

2.5.3.文本格式化

使用java.text.MessageFormat.format:
valmsg=java.text.MessageFormat.format(
"At{1,time}on{1,date},therewas{2}onplanet{0}.",
"Hoth",newjava.util.Date(),"adisturbanceintheForce")
输出At17:50:34on2010-7-20,therewasadisturbanceintheForceonplanetHoth.方法2:"mynameis%s,ageis%d."format("james",30)//mynameisjames,ageis30.注意:format还可以这么用"%s-%d:%1$sis%2$d."format("james",30)//james-30:jamesis30."%2$dage'sman%1$s:%2$d"format("james",30)//30age'smanjames:30

2.6.Null,None,Nil,Nothing

NullTrait,其唯一实例为null,是AnyRef的子类,*不是*AnyVal的子类
NothingTrait,所有类型(包括AnyRef和AnyVal)的子类,没有实例
NoneOption的两个子类之一,另一个是Some,用于安全的函数返回值
Unit无返回值的函数的类型,和java的void对应
Nil长度为0的List

2.7.==和eq

Scala的==很智能,他知道对于数值类型要调用Java中的==,ref类型要调用Java的equals()"hello"=="Hello".toLowerCase()在java中为false,在scala中为trueScala的==总是内容对比
基本类型Int,Double,比值
其他类型相当于A.equals(B)
eq才是引用对比例如:vals1,s2="hello"vals3=newString("hello")s1==s2//trues1eqs2//trues1==s3//true值相同s1eqs3//false不是同一个引用

2.8.Option[T]

2.8.1.概念

lOption[T]可以是任意类型或者空,但一旦声明类型就不能改变;lOption[T]可完美替代Java中的null,可以是Some[T]或者None;lOption实现了map,flatMap,andfilter接口,允许在'for'循环里使用它;函数返回值能被统一处理了:
没有Option的日子现在
deffind(id:Long):Person=...deffind(id:Long):Option[Person]=...
返回Person或者null返回Some[Person]或者None
返回null不特殊处理会抛:NullPointerExceptions返回值直接getOrElse或者列表操作
类比:Java的Stringx.split返回null类比:Java的Stringx.split返回newString[0]
结论:函数永远不要返回null值,如果输入有问题或者抛异常,返回Option[T]
参数有效性检查没有那么烦人了:
没有Option的日子现在
defblank(s:String)=if(s==null)falseelse{s.toList.forall(_.isWhitespace)}defblank(s:String)=Option(s).toList.forall(_.forall(_.isWhitespace))
结论:尽可能地不要浪费代码去检测输入,包装成Option[T]来统一处理

2.8.2.使用

Some(3).getOrElse(4)//3None.getOrElse(4)//4例如打印key=3的value:写法1:defp(map:Map[Int,Int])=println(map(3))p(Map(1->100,2->200))//抛异常写法2:defp(map:Map[Int,Int])=println(mapget3getOrElse"...")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{caseSome(v)=>k+":"+vcaseNone=>"notfound"}}defmain(args:Array[String]):Unit={println(m(1))//100println(m(2))//200println(m(3))//300println(m(4))//"notfound"println(m(-1))//"notfound"}例子2:vall=List(Some(100),None,Some(200),Some(120),None)for(Some(s)<-l)yields//List(100,200,120)或lflatMap(x=>x)//List(100,200,120)例子3:Option结合flatMapdeftoint(s:String)=try{Some(Integer.parseInt(s))}catch{casee:Exception=>None}List("123","12a","45")flatMaptoint//List(123,45)List("123","12a","45")maptoint//List(Some(123),None,Some(45))

2.9.区分<-,=>,->

<-for(i<-0until100)
用于for循环,符号∈的象形
=>List(1,2,3).map(x=>x*x)((i:Int)=>i*i)(5)//25用于匿名函数也可用在import中定义别名:importjavax.swing.{JFrame=>jf}
->Map(1->"a",2->"b")用于Map初始化,也可以不用->而写成Map((1,"a"),(2,"b"))

2.10.match..case(switch)

2.10.1.和switch..case的区别

Java里面的写法:switch(n){case(1):...;break;case(2):...;break;default:...;}变成Scala写法:defm(n:String)=nmatch{case"a"|"b"=>...//这个比较好case"c"=>...case_=>...}匹配值每个case..=>结束不用写break了,_相当于default

2.10.2.匹配数据类型

match可以很简单地匹配数据类型(不需要isInstanceOf[T]):deff(v:Any)=vmatch{casenull=>"null"casei:Int=>i*100cases:String=>scase_=>"others"}注意:上面case中的i、s都叫模式变量f(null)//"null"f(5)//500f("hello")//"hello"f(3.14)//"others"注意:自定义类型如果也要匹配,需要用caseclass

2.10.3.命令行参数解析例子

/**Basiccommandlineparsing.*/
objectMain{
varverbose=false//记录标识,以便能同时对-h和-v做出响应
defmain(args:Array[String]){
for(a<-args)amatch{
case"-h"|"-help"=>
println("Usage:scalaMain[-help|-verbose]")
case"-v"|"-verbose"=>
verbose=true
casex=>//这里x是临时变量
println("Unknownoption:'"+x+"'")
}
if(verbose)println("Howareyoutoday?")
}
}

2.10.4.使用case的递归函数

写法1:deffac(n:Int):Int=nmatch{case0=>1case_=>n*fac(n-1)}写法2(使用映射式函数):deffac:Int=>Int={case0=>1casen=>n*fac(n-1)}
写法3(使用尾递归):
deffac:(Int,Int)=>Int={case(0,y)=>ycase(x,y)=>fac(x-1,x*y)
}
fac(5,1)//120
写法4(reduceLeft):
deffac(n:Int)=1tonreduceLeft(_*_)
implicitdeffoo(n:Int)=new{def!=fac(n)}
5!//120
写法5:(最简洁高效)
deffac(n:Int)=(1:BigInt)tonproduct
fac(5)//120

2.10.5.变量匹配

常量匹配很简单,即case后跟的都是常量;
变量匹配需要注意,case后跟的是match里面的临时变量,而不是其他变量名:
3match{
casei=>println("i="+i)//这里i是模式变量(临时变量),就是3
}
vala=10
20match{casea=>1}//1,a是模式变量,不是10
为了使用变量a,必须用`a`:
20match{case`a`=>1;caseb=>-1}//-1,`a`是变量10
或者用大写的变量:
valA=10
20match{caseA=>1;caseb=>-1}//-1,大写A是变量10

2.10.6.case..if条件匹配

写法1:
(1to20)foreach{casexif(x%15==0)=>printf("%2d:15n\n",x)casexif(x%3==0)=>printf("%2d:3n\n",x)casexif(x%5==0)=>printf("%2d:5n\n",x)casex=>printf("%2d\n",x)}
写法2:
(1to20)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

varf=openFile()try{f=newFileReader("input.txt")}catch{caseex:FileNotFoundException=>//Handlemissingfilecaseex:IOException=>//HandleotherI/Oerror}finally{f.close()}

2.12.require

deff(n:Int)={require(n!=0);1.0/n}deff(n:Int)={require(n!=0,"ncan'tbezero");1.0/n}f(0)//java.lang.IllegalArgumentException:requirementfailed:ncan'tbezerorequiremethodtakesonebooleanparameter.Ifthepassedvalueistrue,requirewillreturnnormally,otherwise,requirethrouanIllegalArgumentException
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐