scala学习笔记之lang1

lang

2.1.和Java的异同

2.1.1.语法

Java++:增加的语法 -》纯OO;操作符重载;closure;使用trait进行mixin组合;existential type(_);抽象类型(type T) class C1[T]{...};模式匹配                                                       Java--:删减的语法-》 静态成员;原生数据类型;break、continue;接口;通配符List, import pkg.*;;原始类型class C1<T> {...};enum枚举

注:existential type——和Java互操作时进行对应, 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调用Java的方法时,会碰到有Scala的保留字,如Thread.yield(); 这在Scala中是非法的,专门有个解决办法,写成:Thread.`yield`()   注意:没有break和continue

2.2.2.变量标识

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

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对应的默认值 注意:仅 var可用"_"表示缺省值赋值。 使用val _ 缺省 会在运行时报错:unbound placeholder parameter

val不可变,相当于const/final,但如果val为数组或者List,val的元素可以赋值;val pi = 3. //相当于3.0d ; val pi = 3.f //相当于3.0f 提示:向函数式风格推进的一个方式,就是尝试不用任何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个到多个

使用正则表达式定义: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的区别

val:定义时就一次求值完成,保持不变 val f = 10+20 // 30

lazy:定义时不求值,第一次使用时完成求值,保持不变 lazy f = 10+20 // f // 30

def:定义时不求值,每次使用时都重新求值 (无参,缺省返回值类型的函数定义)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自动对应到Java原始类型,提高运行效率。Unit对应java的void,用asInstanseOf[T]方法来强制转换类型: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统一了原生类型和引用类型。

Any统一原生类型和引用类型

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可以转化为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

例如: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) //相当于"Hello".toUpperCase

2.5.1.类型转换

"101".toInt // 101,无需Integer.parseInt("101");   "3.14".toFloat // 3.14f   ;   101.toString  ;  3.14.toString   ;    转换整个列表: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,用于安全的函数返回值

Unit:无返回值的函数的类型,和java的void对应

Nil: 长度为0的List

2.7.==和eq

Scala的==很智能,他知道对于数值类型要调用Java中的==,ref类型要调用Java的equals()  "hello"=="Hello".toLowerCase()  在java中为false,在scala中为true ; Scala的==总是内容对比基本类型Int,Double,比值, 其他类型 相当于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实现了map, flatMap, and filter接口,允许在'for'循环里使用它;

函数返回值能被统一处理了:

没有Option的日子 def find(id:Long):Person = ...  返回Person或者null  返回null不特殊处理会抛:NullPointerExceptions  类比:Java的Stringx.split返回null

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

结论:函数永远不要返回null值,如果输入有问题或者抛异常,返回Option[T]

参数有效性检查没有那么烦人了:没有Option的日子: def blank(s:String) =if (s==null) false else{s.toList.forall(_.isWhitespace) }   现在: def blank(s:String) =Option(s).toList.forall(_.forall(_.isWhitespace)) 结论:尽可能地不要浪费代码去检测输入,包装成Option[T]来统一处理

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结合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.区分<-,=>,->

<-     for (i <- 0 until 100)   用于for循环,符号∈的象形

=>     List(1,2,3).map(x=> x*x)   ((i:Int)=>i*i)(5) // 25      用于匿名函数  也可用在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的区别

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

2.10.2.匹配数据类型

match可以很简单地匹配数据类型(不需要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.命令行参数解析例子

/** Basic command line parsing. */

object Main {  var verbose = false //记录标识,以便能同时对-h和-v做出响应

def main(args: Array[String]) {

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

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

case => //这里x是临时变量   println("Unknown option: '"+ x +"'") }

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

2.10.4.使用case的递归函数

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

写法2(使用映射式函数):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") } catchcase 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 内含一个bool型参数,如果返回为true,则正常返回;否则 抛出参数非法异常。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,311评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,339评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,671评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,252评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,253评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,031评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,340评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,973评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,466评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,937评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,039评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,701评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,254评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,259评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,485评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,497评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,786评论 2 345

推荐阅读更多精彩内容

  • Scala的集合类可以从三个维度进行切分: 可变与不可变集合(Immutable and mutable coll...
    时待吾阅读 5,802评论 0 4
  • FP 3.1.函数 函数的地位和一般的变量是同等的,可以作为函数的参数,可以作为返回值。传入函数的任何输入是只读的...
    时待吾阅读 1,100评论 0 2
  • 22.13.main方法 Scala的main方法(类似java的static方法)必须定义在一个object内:...
    时待吾阅读 749评论 0 0
  • 数组是一种可变的、可索引的数据集合。在Scala中用Array[T]的形式来表示Java中的数组形式 T[]。 v...
    时待吾阅读 942评论 0 0
  • 背景 一年多以前我在知乎上答了有关LeetCode的问题, 分享了一些自己做题目的经验。 张土汪:刷leetcod...
    土汪阅读 12,724评论 0 33