Scala 自学笔记

1、变量声明
val answer = 8 * 5 + 2; //常量
var counter = 0;	//变量
//在必要的时候 ,可以指定类型
val greeting:String = null
val greeting:Any = "Hello"
//可以将多个值或变量放在一起声明
val xmax, ymax = 100 //xmax 和 ymax设为100
var greeting, message:String = null // 都被设为字符串,被初始化为null

常用类型
常用数值类型
Byte Char Short Int Long Float Double Boolean 
BigInteger BigDecimal 用于任意大小的数字

scala的 StringOps, RichInt, RichDouble, RichChart 给基本类型提供了很多方法,在调用时会自动隐式转换
"Hello".intersect("World")  //输出"lo"
1.to(10) //Int值1首先被转换为RichInt,然后调用to方法

类型转换
不像java用 强制类型转换,而是用方法
99.44.toInt 		//99, 这里不带参数,并且不改变当前对象的方法 通常不实用圆括号
99.toChart 		//'c'
99.toString 		//"99"
"99.44".toDouble 	// 99.44

apply方法

"Hello"(4) // '0'
实际上是StringOps类的apply方法
def apply(n:Int) : Char
"Hello".apply(4) // 完整写法

BigInt伴生对象的apply方法:
BigInt("1234567890") // BigInt.apply("1234567890")

BigInt("123") * BigInt("123")

数组Array,也是伴生对象
Array(1,4,9,16) 


2、控制结构和函数
if (x > 0) 1 else -1
可以将if/else表达式的值赋给变量
val s = if(x > 0) 1 else -1

每个表达式都有一个类型
if(x > 0) 1 else -1  // Int
if(x > 0) "p" else -1 // Any (Int 和String的超类)
if(x > 0) 1   // (),Unit类,因为可能没有输出值,即if(x >0) 1 else ()

while(n > 0){
  r = r*n
  n -=1
}

for 循环
for( i <- 表达式)

for( i <- 1 to 10)
  r = r*i

val s = "Hello"
var sum = 0
for( i <- 0 until s.length)
  sum+= s(i)

简化版:
var sum = 0
for(ch <- "Hello") sum+=ch

高级for循环和for 推导式
for( i <- 1 to 3; j <- 1 to 3)  println((10 * i + j)+ "")
11 12 13 21 22 23 31 32 33

for(i <- 1 to 3; j <- 1 to 3 if i != j)print((10 * i + j)+ "")
12 13 21 23 31 32
注意在if前没有分号

for(i <- 3; from = 4 - i ; j <- from to 3) print((10 * i + j) + " ")
 31 22 23 31 32 33

for( i <- 1 to 10) yield i % 3
生成 Vector(1,2,0,1,2,0,1,2,0,1)

推导式生成的集合与第一个生成器是类型兼容的:
for( c<- "Hello"; i<- 0 to 1) yield (c + i).toChar
"Hilflmlmop"

for(i <- 0 to 1; c <- "Hello") yield (c + i).toChar
Vector('H','e','l',''l','o','I','f','m','m','p')

函数
def abs(x:Double) = if(x >=0) x else -x
def fac(n:Int) = {
  var r=1
  for( i<- 1 to n) r=r*i
  r // 无需return,最后一行即返回值
}

一般定义函数无需指定返回类型,Scala可以通过=符号右侧的表示式的类型推断返回类型,除非是递归函数。
def fac(n:Int) :Int = if(n<=0) 1 else n* fac(n-1)// 如果没有返回类型,Scala无法校验 n*fac(n-1)的类型是Int

默认参数和带名参数
def decorate(str:String, left:String="[", right:String ="]") = left + str +right

decorate("Hello", "<<<", ">>>")  			// <<<Hello>>>
decorate("Hello","<<<") 				// <<<Hello]
decorate(left = "<<<", str = "Hello" , right = ">>>") 	// 指定参数名,<<<Hello>>>
decorate("Hello", right=">>>")				// 混用

变长参数
def sum(args: Int*){
  var result = 0
  for (arg <- args) result += arg
  result
}
val s = sum(1,4,9,16,25) 				//函数得到 类型Seq的参数

val s = sum(1 to 5) 					// 错误
val s = sum(1 to 5: _*) 				//将 1 to 5当做参数序列处理

递归中使用
def recursiveSum(args : Int *): Int = {
  if (args.length ==0) 0
  else args.head + recursiveSum(args.tail:_*) 		// head是首个元素, tail是所有其他元素的序列,是一个Seq
}

过程
过程不返回任何值,可以略去=号
def box(x:String) {
  println(x)
}
也可以显式声明Unit返回类型
def box(x:String) :Unit = {}

懒值
lazy val words = scala.io.Source.fromFile("/usr/share/dict/words").mkString //直到我们首次对它取值才会初始化。

可以把懒值当做介于 val和def的中间状态:
val words = scala.io.Source.fromFile("/usr/share/dict/words").mkString//在words被定义时即被取值
lazy val words= scala.io.Source.fromFile("/usr/share/dict/words").mkString//在首次调用
def words= scala.io.Source.fromFile("/usr/share/dict/words").mkString//在每一次被使用时

异常
if (x >= 0 )  { sqrt(x) }
else throw new IllegalArgumentException("x should not be negative")
throw 表达式有特殊的类型Nothing, 在if/else中,如果以个分支的类型为Nothing, 那么表达式的类型就是 另一个分支的类型, 在这里就是 Double
捕获异常,使用模式匹配
try{

}catch{
  case _: MalformedURLException => println("Bad Url:" + url)
  case ex: IOException => ex.printStackTrace()
}

var in = new URL("http://xxx.com").openStream()
try{
  process(in)
}finally{
  in.close()
}
try{...} catch{...} finally{...}

3、数组
定长数组
val nums = new Array[Int](10) 			// 都是0
val a = new Array[String](10) 			// 都是null
val s = Array("Hello", "World") 		// Array伴生对象的apply 方法
s(0) = "Goodbye" 				//Array("Goodbye","World")

变长数组
import scala.collection.mutable.ArrayBuffer
val b = ArrayBuffer[Int]() 			// 伴生对象的apply
//或者 new ArrayBuffer[Int]
b += 1       					//(1)
b += (1,2,3,5) 					// (1,1,2,3,5)
b ++= Array(8,13,21) 				// 可以用++=追加任何集合 (1,1,2,3,5,8,13,21)
b.trimEnd(5)   					//移除最后5个元素 , (1,1,2)

b.insert(2,6)  					// (1,1,6,2)
b.insert(2,7,8,9)				// (1,1,7,8,9,6,2)
b.remove(2) 					// (1,1,8,9,6,2)
b.remove(2,3)					//(1,1,2)

b.toArray  					// Array(1,1,2) ,变长转定长
a.toBuffer 					// 定长转变长

遍历数组
for(i <- 0 until.a.length)
  println(i + ": " + a(i))

如果在循环体中不需要下表
for(elem <- a )
  println(elem)

数组转换
val a = Array(2,3,5,7,11)
val result = for(elem <- a) yield 2 * elem
// result 是 Array(4, 6, 10 , 14, 22)

for(elem <- a if elem %2 ==0) yield 2 * elem
另一种做法
a.filter(_ % 2 ==2).map(2 * _)
移除第一个负数之外的所有负数
首先收集需要保留的下标:
var first = true
val indexs = for(i <-0 until a.length if first || a(i) >=0) yield {
  if(a(i)<0) first = false; i  }// 按书序记录了所有正数和第一个负数的小标,其他负数的小标都丢弃了
for(j <- 0 until.indexs.length) a(j) = a(index(j))//将元素移动到该去的位置 a.trimEnd(a.length - indexs.length)//并截断尾端//这里主要是 小标处理

常用算法
Array(1,7,2,9).sum  //19
ArrayBuffer("Mary","had","a","little",'lamb').max   //"little"

val b = ArrayBuffer(1,7,2,9)
val bSorted = b.sorted(_ < _) // (1,2,7,9) 这里b没有改变,可以提供一个比较函数,用sortWith方法

val a = Array(1,7,2,9)
scala.util.Sorting.quickSort(a) // 此方法不适于ArrayBuffer

a.mkString(" and ") // "1 and 2 and 7 and 9"
a.mkString("<", "," , ">")// "<1,2,7,9>"


多维数组
Array[Array[Double]] , 也可以通过ofDim方法:
val matrix = Array.ofDim[Double](3,4) // 三行,四列
matrix(row)(col) = 42

创建不规则的多维数组
var triangle = new Array[Array[Int]](10)
for(i <- 0 until triangle.length)
  triangle(i) = new Array[Int](i+1)

与Java的互操作
通过引入scala.collection.JavaConversions里的隐式转换方法,可以自动包装成Java对象,如列表等。
import scala.collection.JavaConversions.bufferAsJavaList
import scala.collection.mutable.ArrayBuffer
val command = ArrayBuffer("ls", "-all" , "/home/clat")
val pb = new ProcessBuilder(command) 
// Scala to Java, Scala缓冲数组被包装成一个实现了java.until.List接口的Java类的对象

反过来,把Java.until.List,自动转换成一个Buffer
import scala.collection.JavaConversions.asScalaBuffer
import scala.collection.mutable.Buffer
val cmd :Buffer[String] = pb.command() 
// java to scala, 不能使用ArrayBuffer, 包装起来的对象仅能保证是个Buffer

4、映射和元素
val scores = scala.collection.immutable.Map("Alice" -> 10, "Bob" -> 3, "Cindy" -> 8 ) 	//不可变Map[String, Int]

val scores = scala.collection.mutable.Map("Alice" -> 10, "Bob" -> 3, "Cindy" -> 8 )	//可变Map[String, Int]

val scores = new scala.collection.mutable.HashMap[String, Int]				//定义一个空的Map,需要给出类型参数

Map 是对偶的集合, -> 操作符 用来创建对偶, "Alice" -> 10 产出的值是 ("Alice", 10)
所以也可以用下面的方法定义 Map:
val scores = Map(("Alice",10),("Bob",3),("Cindy",8)) //只不过 -> 操作符 比 圆括号 更易读,更符合大家对Map的直观感觉。
获取Map中的值
val bobScore = scores("Bob") // 类似java的 scores.get("Bob"), 如果不存在,则抛出异常
val bobsScore = if(scores.contain("Bob")) scores("Bob") else 0 // 可以用contains 来判断

val bobsScore = scores.getOrElse("Bob",0) //便捷写法



更新Map
可变的Map
score("Bob") = 10 //更新
scores("Fred") = 7 //增加
scores += ("Bob" -> 10, "Fred"-> 7)
scoers -= "Alice"

不可变Map, 假定当前scores是不可变
val new Scores = scores + ("Bob" -> 10, "Fred"-> 7) // 产生一个新的Map
或者 当 scores 是 var变量
var scores = ...
scores = scores + ("Bob" -> 10, "Fred"-> 7)
scores = scores - "Alice"

迭代Map
for( (k, v) <- Map) 处理 k 和 v
scores.keySet  //一个类似 Set("Bob", "Cindy", "Alice")这样的集合
for(v <- scores.values) prinltn(v) // 打印 10 8 7 10
for( (k, v) <- map) yield ( v, k )//反转Map

排序Map
默认Scala给的是 哈希表,
val scores = scala.collections.immutable.SortedMap("Alice" -> 10, "Fred" -> 7, "Bob" -> 3, "Cindy" -> 8) // 如果需要<strong>排序</strong>,需要用树形Map

在Scala(2.9)中,还没有可变的 树形Map,只能用java的TreeMap

如果想按<strong>插入顺序</strong>访问所有键,可以用LinkedHashMap
val months = scala.collection.mutable.LinkedHashMap("Jan" ->1, ,"Feb" ->2, "Mar" ->3 , ...)

与Java的互操作
Java -> Scala
引入语句
import scala.collection.JavaConversions.mapAsScalaMap
val scores: scala.collection.mutable.Map[String, Int] = new java.util.TreeMap[String,Int]

import scala.collection.JavaConversions.propertiesAsScalaMap
val props:scala.collection.Map[String,String] = System.getProperties()

Scala -> Java
import scala.collection.JavaConversions.mapAsJavaMap
import java.awt.font.TextAttribute._
val attrs = Map(FAMILY -> "Serif" , SIZE -> 12)
val font = new javal.awt.Font(attrs) //该方法预期一个Java Map

元组
Map是k/v对偶的集合,对偶是元组最简单的形态, 元组是不同类型的值得聚集。
val t = (1,3.14,"Fred") // Tuple3[Int, Double, java.lang.String]
val second = t._2 // 元组位置从1开始,这里是 3.14
//t._2 可以写成 t _2, 中间变空格
val (first, second, thrid) = t // first设为1, second 设为3.14, third设为 "Fred"
当不需要所有部件时,,可以在不需要的位置上使用:
val (first, second, _) = t

元组用于函数需要范围不止一个值得情况,如StringOps的partition方法,返回包含满足和不满足某条件的字符:
"New York".partition(_.isUpper) // ("NY" , "ew ork")

拉链操作
val symbols = Array("<", "-", ">")
val counts = Array(2, 10 , 2)
val pairs = symbols.zip(count) // 输出对偶的数组, Array(("<", 2), ("-", 10), (">", 2))
for((s,n) <- pairs) Console.print(s * n)// <<---------->>
用toMap方法可以将对偶的集合转换成Map
keys.zip(values).toMap//keys是k集合, values是与之平行对应的v集合


 
 
 
 


  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值