快學scala筆記.
阿新 • • 發佈:2018-12-25
第一章 基礎
val 定義的值實際上是一個常量
var 宣告其值可變的變數
val xmax,ymax = 100
var greeting,message: String = null
1.3 常用型別
Scala的7種數值型別:Byte、Char、Short、Int、Long、Float和Double
1、toString()
2、to(10)
"Hello".intersect("World")
1.4 算術和操作符過載
val answer = 8 * 5 + 2
scala 提供 += 或者 -=
counter += 1
1.5呼叫函式和方法
sqrt(2)
pow(2,4)
min(3,Pi)
import scala.math._ //在scala中,_字元是“萬用字元”,類似Java中的*
BigInt.probablePrime(100,scala.util.Random)
1.6 apply方法
"Hello"(4)
def apply(n: Int): Char
"Hello".apply(4)
def count(p: (Char) => Boolean) : Int
第一章習題
1 簡介
近期對Scala比較感興趣,買了本《快學Scala》,感覺不錯。比《Programming Scala:Tackle Multi-Core Complexity on the Java Virtual Machine》好很多。 是本不錯的入門書。而且每個章節都設定了難度級別,每章有習題,可以鞏固Scala語法。
本文的目的就是針對這些習題進行解答
2 基礎
2.1 在Scala REPL中鍵入3,然後按Tab鍵。有哪些方法可以被應用?
這個。。。。直接操作一遍就有結果了.此題不知是翻譯的問題,還是原題的問題,在Scala REPL中需要按3. 然後按Tab才會提示。 直接按3加Tab是沒有提示的。下面是結果
Scala程式碼
1.!= ## % & * +
2.- / < << <= ==
3.> >= >> >>> ^ asInstanceOf
4.equals getClass hashCode isInstanceOf toByte toChar
5.toDouble toFloat toInt toLong toShort toString
6.unary_+ unary_- unary_~ |
列出的方法並不全,需要查詢全部方法還是需要到Scaladoc中的Int,Double,RichInt,RichDouble等類中去檢視。
2.2 在Scala REPL中,計算3的平方根,然後再對該值求平方。現在,這個結果與3相差多少?(提示:res變數是你的朋友)
依次進行計算即可
Scala程式碼
1.scala> scala.math.sqrt(3)
2.warning: there were 1 deprecation warnings; re-run with -deprecation for details
3.res5: Double = 1.7320508075688772
4.
5.scala> res5*res5
6.res6: Double = 2.9999999999999996
7.
8.scala> 3 - res6
9.res7: Double = 4.440892098500626E-16
2.3 res變數是val還是var?
val是不可變的,而var是可變的,只需要給res變數重新賦值就可以檢測res是val還是var了
Scala程式碼
1.scala> res9 = 3
2.<console>:8: error: reassignment to val
3. res9 = 3
4. ^
2.4 Scala允許你用數字去乘字串—去REPL中試一下"crazy"*3。這個操作做什麼?在Scaladoc中如何找到這個操作?
Scala程式碼
1.scala> "crazy"*3
2.res11: String = crazycrazycrazy
從程式碼可以推斷,*是"crazy"這個字串所具有的方法,但是Java中的String可沒這個方法,很明顯。此方法在StringOps中。
2.5 10 max 2的含義是什麼?max方法定義在哪個類中?
直接在REPL中執行
Scala程式碼
1.scala> 10 max 2
2.res0: Int = 10
3.
4.scala> 7 max 8
5.res1: Int = 8
6.
7.scala> 0 max 0
8.res2: Int = 0
可以看出,此方法返回兩個數字中較大的那個。此方法Java中不存在,所以在RichInt中。
2.6 用BigInt計算2的1024次方
簡單的API呼叫
Scala程式碼
1.scala> BigInt(2).pow(1024)
2.res4: scala.math.BigInt = 1797693134862315907729305190789024733617976978942306572734300811577326758055009631327084773224
3.075360211201138798713933576587897688144166224928474306394741243777678934248654852763022196012460941194530829520850057688
4.38150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137216
2.7 為了在使用probablePrime(100,Random)獲取隨機素數時不在probablePrime和Radom之前使用任何限定符,你需要引入什麼?
so easy. import需要的包啊。Random在scala.util中,而probablePrime是BigInt中的方法,引入即可
Scala程式碼
1.import scala.math.BigInt._
2.import scala.util.Random
3.
4.probablePrime(3,Random)
2.8 建立隨機檔案的方式之一是生成一個隨機的BigInt,然後將它轉換成三十六進位制,輸出類似"qsnvbevtomcj38o06kul"這樣的字串。
查閱Scaladoc,找到在Scala中實現該邏輯的辦法。 到BigInt中查詢方法。
Scala程式碼
1.scala> scala.math.BigInt(scala.util.Random.nextInt).toString(36)
2.res21: String = utydx
2.9 在Scala中如何獲取字串的首字元和尾字元?
Scala程式碼
1.//獲取首字元
2."Hello"(0)
3."Hello".take(1)
4.//獲取尾字元
5."Hello".reverse(0)
6."Hello".takeRight(1)
2.10 take,drop,takeRight和dropRight這些字串函式是做什麼用的?和substring相比,他們的優點和缺點都是哪些?
查詢API即可 take是從字串首開始獲取字串,drop是從字串首開始去除字串。 takeRight和dropRight是從字串尾開始操作。
這四個方法都是單方向的。 如果我想要字串中間的子字串,那麼需要同時呼叫drop和dropRight,或者使用substring
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
第二章 控制結構和函式
2.1 條件表示式
if(x > 0) 1 else -1
val s = if(x > 0) 1 else -1
混合型表示式:
if(x>0) "positive" else -1
2.2 語句終止
val n = 12
if(n>0) { r = r * n; n -= 1}
s = s0 + (v - v0) * t + 0.5 * (a-a0) * t * t
if(n > 0){
r = r * n
n -= 1
}
2.3 塊表示式和賦值
val distance = { val dx = x - x0; val dy = y - y0; sqrt(dx * dx + dy * dy)}
{ r = r * n; n -= 1}
2.4 輸入和輸出
print("Answer: ")
println(42)
println("Answer: " + 42)
println("Hello,%s! You are %d years old.\n","Fred",42)
val name = readLine("Your name: ")
print("Your age: ")
val age = readInt()
printf("Hello, %s! Next year,your will be %d.\n",name,age + 1)
2.5 迴圈
while(n > 0){
r = r * n
n -= 1
}
2.6 高階for迴圈和for推導式
for(i <- 1 to 3; j <- 1 to 3) print((10 * i + j) + " ")
for(i <- -1 to 3;j <- 1 to 3 if i != j) print((10 * i + j) + " ")
for(i <- 1 to 3; from = 4 - i;j <- from to 3) print((10 * i + j) + " ")
for(i <- 1 to 10 yield i % 3)
for(c <- "Hello"; i<- 0 to 1) yield (c + i).toChar
for(i <- 0 to 1;c <- "Hello") yield (c + i).toChar
for{ i<- 1 to 3
from = 4 -i
j <- from to 3
}
2.7 函式
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
}
對於遞迴函式,我們必須指定返回型別。例如:
def fac(n: Int): Int = if (n <= 0) 1 else n * fac(n - 1)
2.8 預設引數和帶名引數
def decorate(str: String,left: String = "[",right: String = "]") = left + str + right
decorate(left = "<<<",str = "Hello", right = ">>>")
decorate("Hello",right = "]<<<")
2.9 變長引數
def sum(args: Int*) = {
var result = 0
for(arg <- args) result += arg
result
}
val s = sum(1,4,9,16,25)
val s = sum(1 to 5)
val s = sum(1 to 5: _*)
def recursiveSum(args: Int*): Int = {
if(args.length == 0) 0
else args.head + recursiveSum(args.tail: _*)
}
val str = MessageFormat.format("The answer to {0} is {1}")
2.10 過程
Scala 對於不返回值的函式有特殊的表示法。如果函式體包含在花括號當中但沒有前面的=號,那麼返回型別就是Unit。
這樣的函式被稱做過程(procedure)。過程不返回值,我們呼叫它僅僅是為了它的副作用。舉例來說,如下過程把一個字串列印在一個框中,就像這樣:
--------
|hello|
--------
由於過程不返回任何值,所以我們可以略去=號
def box(s: String){
var border = "-" * s.length + "--\n"
println(border + "|" + s + "|\n" + border)
}
顯示宣告Unit返回型別
def box(s: String): Unit={
var border = "-" * s.length + "--\n"
println(border + "|" + s + "|\n" + border)
}
2.11 懶值
當val被宣告為lazy時,它的初始化將被推遲,直到我們首次對它取值。例如,
lazy val words = scala.io.Source.fromFile("/usr/share/dict/words").mkString
懶值對於開銷較大的初始化語句而言十分有用。它們還可以應對其他初始化問題,比如迴圈依賴。
你可以把懶值當做是介於val和def的中間狀態。對比如下定義:
//在worlds被定義時被取值
val words = scala.io.Source.fromFile("/usr/share/dict/words").mkString
//在words被首次使用時取值
lazy val words = scala.io.Source.fromFile("/usr/share/dict/words").mkString
//在每一次words被使用時取值
def words = scala.io.Source.fromFile("/usr/share/dict/words").mkString
2.12 異常
Scala異常工作機制和Java或C++一樣
throws new IllegalArgumentException("x should not be negative")
if(x >= 0){
sqrt(x)
} else throw new IllegalArgumentException("x should not be negative")
捕獲異常的語法採用的是模式匹配
try{
process(new URL("http://horstmann.com/fred-tiny.gif"))
} catch{
case _: MalformedURLException => println("Bad URL:" + url)
case ex: IOException => ex.printStackTrace()
}
var in = new URL("http://horstman.com/fred.gif").openStream()
try{
process(in)
} finally {
in.close()
}
try{...} catch{...} finally{...}
try{try{...} catch{...}} finally {...}
習題:
2 控制結構和函式
2.1 一個數字如果為正數,則它的signum為1;如果是負數,則signum為-1;如果為0,則signum為0.編寫一個函式來計算這個值
簡單的邏輯判斷
def signum(num:Int){if(num>0)print(1)else if(num<0)print(-1)else print(0)}
Scala中已經有此方法了,剛才查詢API的時候,應該能看到
BigInt(10).signum
2.2 一個空的快表示式{}的值是什麼?型別是什麼?
在REPL中就能看出來了
scala> val t = {}
t: Unit = ()
可以看出,它的值是()型別是Unit
2.2 指出在Scala中何種情況下賦值語句x=y=1是合法的。(提示:給x找個合適的型別定義)
題目已經給了明確的提示了。本章節中已經說過了,在scala中的賦值語句是Unit型別。所以只要x為Unit型別就可以了。
scala> var y=4;
y: Int = 4
scala> var x={}
x: Unit = ()
scala> x=y=7
x: Unit = ()
這也再次證明了{}是Unit型別
2.4 針對下列Java迴圈編寫一個Scala版本:
for(int i=10;i>=0;i–)
System.out.println(i);
使用Scala版本改寫就OK了
for(i <- 0 to 10 reverse)print(i)
2.5 編寫一個過程countdown(n:Int),列印從n到0的數字
這個就是將上面的迴圈包裝到過程中而已。還是換個寫法吧。
def countdown(n:Int){
0 to n reverse foreach print
}
2.6 編寫一個for迴圈,計算字串中所有字母的Unicode程式碼的乘積。舉例來說,"Hello"中所有字串的乘積為9415087488L
scala> var t:Long = 1
t: Long = 1
scala> for(i <- "Hello"){
| t = t * i.toLong
| }
scala> t
res57: Long = 9415087488
2.7 同樣是解決前一個練習的問題,但這次不使用迴圈。(提示:在Scaladoc中檢視StringOps)
scala> var t:Long = 1
t: Long = 1
scala> "Hello".foreach(t *= _.toLong)
scala> t
res59: Long = 9415087488
2.8 編寫一個函式product(s:String),計算前面練習中提到的乘積
def product(s:String):Long={
var t:Long = 1
for(i <- s){
t *= i.toLong
}
t
}
2.9 把前一個練習中的函式改成遞迴函式
配合前一章的take和drop來實現
def product(s:String):Long={
if(s.length == 1) return s.charAt(0).toLong
else s.take(1).charAt(0).toLong * product(s.drop(1))
}
2.10 編寫函式計算xn,其中n是整數,使用如下的遞迴定義:
•xn=y2,如果n是正偶數的話,這裡的y=x(n/2)
•xn = x*x(n-1),如果n是正奇數的話
•x0 = 1
•xn = 1/x(-n),如果n是負數的話
不得使用return語句
def mi(x:Double,n:Int):Double={
if(n == 0) 1
else if (n > 0 && n%2 == 0) mi(x,n/2) * mi(x,n/2)
else if(n>0 && n%2 == 1) x * mi(x,n-1)
else 1/mi(x,-n)
}
第3章 陣列相關操作
本章重點包括:
若長度固定則使用Array,若長度可能有變化則使用ArrayBuffer
提供初始值時不要使用new。
用()來訪問元素。
用for(elem <- arr)來遍歷元素
用for(elem <- arr if ...)...yield...來將原陣列轉型為新陣列
Scala陣列和Java陣列可以互操作;用ArrayBuffer,使用scala.collection.JavaConversions中的轉換函式。
3.1 定長陣列
val nums = new Array[Int](10)
val a = new Array[String](10)
val s = Array("Hello","World")
s(0) = "Goodbye"
在JVM中,Scala的Array以Java陣列方式實現。
示例中的陣列的JVM中的型別為java.lang.String[].Int、Double或其他與Java中基本型別對應的陣列都是基本型別陣列。舉例來說,Array(2,3,5,7,11)
3.2 變長陣列:陣列快取
import scala.collection.mutable.ArrayBuffer
val b = ArrayBuffer[Int]()
b += 1
b += (1,2,3,5)
//++=操作符追加任何集合
b ++= Array(8,13,21)
//移除最後5個元素
b.trimEnd(5)
//在下標2之前插入
b.insert(2,6)
//可以插入任意多的元素
b.insert(2,7,8,9)
b.remove(2)
b.remove(2,3)
//構建一個數組緩衝然後呼叫
b.toArray
//將陣列a轉換成一個數組緩衝
a.toBuffer
3.3 遍歷陣列和陣列緩衝
for(i <- 0 until b.length)
println(i + ": " + b(i))
//util是RichInt類的方法,返回所有小於上限的數字。
0 until 10
0 until (b.length,2)
(0 until b.length).reverse
for(elem <- a)
println(elem)
3.4 陣列轉換
val a = Array(2,3,5,7,11)
val result = for(elem <- a) yield 2 * elem
for(elem <- a if elem % 2 == 0) yield 2 * elem
a.filter(_ % 2 == 0).map(2 * _)
a.filter{ _ % 2 == 0} map { 2 * _}
var first = true
var n = a.length
var i = 0
while(i < 0){
if(a(i) >= 0) i+=1
else
if(first){first = false; i += 1}
else {a.remove(i);n -= 1}
}
var first = true
val indexes = for(i <- 0 until a.length if first || a(i) >= 0) yield{
if (a(i) < 0) first = false;
i
}
for(j <- 0 until indexes.length) a(j) = a(indexes(j))
a.trimEnd(a.length - indexes.length)
3.5 常用演算法
Array(1,7,2,9).sum
ArrayBuffer("Mary","had","a","little","lamb").max
val b = ArrayBuffer(1,7,2,9)
val bSorted = b.sorted(_ < _)
val bDescending = b.sorted(_ > _)
val a = Array(1,7,2,9)
scala.util.Sorting.quickSort(a)
a.mkString(" and ")
a.mkString("<",",",">")
a.toString
b.toString
3.6 解讀Scaladoc
3.7 多維陣列
val matrix = Array.ofDim[Double](3,4)
matrix(row)(column) = 42
val triangle = new Array[Array[Int]](10)
for(i <- until triangle.length)
triangle(i) = new Array[Int](i + 1)
3.8 與Java的互操作
import scala.collection.JavaConversions.bufferAsJavaList
import scala.collection.mutable.ArrayBuffer
val command = ArrayBuffer("ls","-a","/home/cay")
val pb = new ProcessBuilder(command)
import scala.collection.JavaConversions.asScalaBuffer
import scala.collection.mutable.Buffer
val cmd: Buffer[String] = pb.command()
1、編寫一段程式碼,將a設定為一個n個隨機整數的陣列,要求隨機數介於0(包含)和n(不包含)之間。
2、編寫一個迴圈,將整數陣列中相鄰的元素置換。例如,Array(1,2,3,4,5)經過置換後變為Array(2,1,4,3,5)
3、重複前一個練習,不過這一次生成一個新的值交換過的陣列。用for/yield
4、給定一個整數陣列,產生一個新的陣列,包含元陣列中的所有正值,以原有順序排列,之後的元素是所有零或負值,以原有順序排序
5、如何計算Array[Double]的平均值?
6、如何重新組織Array[Int]的元素將它們以反序排序?對於ArrayBuffer[Int]你又會怎麼做呢?
7、
第4章 對映和元組
4.1 構造對映
4.2 獲取對映中的值
4.3 更新對映中的值
4.4 迭代對映
4.5 已排序對映
4.6 與Java的互操作
4.7 元組
對映是鍵/值對偶的集合。對偶是元組的最簡單形式--元組是不同型別的值得聚集。
元組的值是通過將單個的值包含在圓括號中構成。例如:
(1,3,14,"Fred")
Tuple3[Int,Double,java.lang.String]
(Int,Double,java.lang.String)
val t = (1,3,14,"Fred")
val secnd = t._2
通常,使用模式匹配來獲取元組的組元,例如:
val (first,second,third) = t //將first設為1,second設為3.14,third設為"Fred"
val (first,second, _) = t
"New York".partition(_.isUpper)
4.8 拉鍊操作
val symbols = Array("<","-",">")
val counts = Array(2,10,2)
val pairs = symbols.zip(counts)
本章的要點包括:
Scala有十分易用的語法來建立、查詢和遍歷對映。
你需要從可變的和不可變的對映中做出選擇。
預設情況下,你得到的是一個雜湊對映,不過你也可以指明要樹形對映。
你可以很容易地在Scala對映和Java對映之間來回切換。
元組可以用來聚集值
4.1 構造對映
val scores = Map("Alice" -> 10,"Bob" -> 3,"Cindy" -> 8)
val scores = scala.collection.mutable.Map("Alice" -> 10,"Bob" -> 3,"Cindy" -> 8)
val scores = new scala.collection.mutable.HashMap[String,Int]
->操作符用來建立對偶
"Alice" -> 10
上述程式碼產出的值:
()
1、設定一個對映,其中包含你想要的一些裝備,以及它們的價格。然後構建另一個對映,採用用一組鍵,但在價格上9折
2、編寫一段程式,從檔案中讀取單詞。用一個可變對映來清點每一個單詞出現的頻率。讀取這些單詞的操作可以使用java.util.Scanner:
val in = new java.util.Scanner(new java.io.File("myfile.txt"))
while(in.hasNext()) 處理 in.next()
最後,打印出所有單詞和它們出現的次數
3、重複前一個練習,這次用不可變的對映。
4、重複前一個練習,這次用已排序的對映,以便單詞可以按順序打印出來。
5、重複前一個練習,這次用java.util.TreeMap並使之適用於Scala API
6、定義一個鏈式雜湊對映,將“Monday”對映到java.util.Calendar.MONDAY,依次類推加入其他日期。展示元素是以插入的順序被訪問的。
7、打印出所有Java系統屬性的表格,類似這樣:
java.runtime.name | Java(TM) SE Runtime Environment
sun.boot.library.path | /home/apps/jdk1.6.0.21/jre/lib/i386
java.vm.version | 17.0-bl6
java.vm.vendor | Sun Microsystems Inc
java.vendor.url | http://java.sun.com/
path.separator | :
java.vm.name | Java HotSpot(TM) Server VM
8、編寫一個函式
9、編寫一個函式
10、當你將兩個字串拉鍊在一起,比如
11、
第5章
5.1 簡單類和無參方法
class Counter{
private var value = 0 //
def increment(){ value += 1}
def current() = value
}
val myCounter = new Counter
myCounter.increment()
println(myCounter.current)
myCounter.current
myCounter.current()
5.2 帶getter和setter的屬性
5.3 只帶getter的屬性
5.4 物件私有欄位
5.5 Bean屬性
import scala.reflect.BeanProperty
class Person{
@BeanProperty var name: String = _
}
將會生成四個方法:
1、name: String
2、name_=(newValue:String):Unit
3、getName():String
4、setName(newValue:String):Unit
class Person(@BeanProperty var name: String)
5.6 輔助構造器
class Person{
private var name = ""
private var age = 0
def this(name: String){
this()
this.name = name
}
def this(name: String,age: Int){
this(name)
this.age = age
}
}
val p1 = new Person
val p2 = new Person("Fred")
val p3 = new Person("Fred",42)
5.7 主構造器
class Person(val name: String,val age: Int){
}
5.8 巢狀類
import scala.collection.mutable.ArrayBuffer
class Network{
class Member(val name: String){
val contacts = new ArrayBuffer[Member]
}
private val members = new ArrayBuffer[Member]
def join(name: String) = {
val m = new Member(name)
members += m
m
}
}
val chstter = new Network
val myFace = new Network
val fred = chatter.join("Fred")
val wilma = chatter.join("Wilma")
fred.contacts += wilma
val barney = myFace.join("Barney")
fred.contacts += barney
object Network{
class Member(val name: String){
val contacts = new ArrayBuffer[Member]
}
}
class Network{
private val members = new
}
第七章 包和引入
7.1 包
package com{
package horstman{
package impattern{
class Employee
}
}
}
package org{
package bigjava{
class Counter
}
}
7.2 作用域規則
package com{
package horstmann{
object Utils{
def percentOf(value: Double,rate: Double) = value * rate / 100
...
}
}
}
package impatient{
class Employee{
def giveRaise(rate: scala.Double){
salary += Utils.percentOf(salary,rate)
}
}
}
7.3 串聯式包語句
7.4 檔案頂部標記法
7.5 包物件
7.6 包可見性
7.7 引入
7.8 任何地方都可以宣告引入
7.9 重新命名和隱藏方法
import java.awt.{Color,Font}
import java.util.{HashMap => JavaHashMap}
import scala.collection.mutable._
import java.util.{HashMap => _,_}
import scala.collection.mutable._
7.10 隱式引入
import java.lang._
import scala._
import Predef._
collection.mutable.HashMap
scala.collection.mutable.HashMap
第8章 繼承
8.1 擴充套件類
class Employee extends Person{
var salary = 0.0
}
8.2 重寫方法
public class Person{
override def toString = getClass.getName + "[name=" + name + "]"
}
8.3 型別檢查和轉換
if(p.isInstanceOf[Employee]){
val s = p.asInstanceOf[Employee]
}
8.4 受保護欄位和方法
8.5 超類的構造
8.6 重寫欄位
8.7 匿名子類
8.8 抽象類
8.9 抽象欄位
8.10 構造順序和提前定義
8.11 Scala繼承層級
8.12 物件相等性
val 定義的值實際上是一個常量
var 宣告其值可變的變數
val xmax,ymax = 100
var greeting,message: String = null
1.3 常用型別
Scala的7種數值型別:Byte、Char、Short、Int、Long、Float和Double
1、toString()
2、to(10)
"Hello".intersect("World")
1.4 算術和操作符過載
val answer = 8 * 5 + 2
scala 提供 += 或者 -=
counter += 1
1.5呼叫函式和方法
sqrt(2)
pow(2,4)
min(3,Pi)
import scala.math._ //在scala中,_字元是“萬用字元”,類似Java中的*
BigInt.probablePrime(100,scala.util.Random)
1.6 apply方法
"Hello"(4)
def apply(n: Int): Char
"Hello".apply(4)
def count(p: (Char) => Boolean) : Int
第一章習題
1 簡介
近期對Scala比較感興趣,買了本《快學Scala》,感覺不錯。比《Programming Scala:Tackle Multi-Core Complexity on the Java Virtual Machine》好很多。 是本不錯的入門書。而且每個章節都設定了難度級別,每章有習題,可以鞏固Scala語法。
本文的目的就是針對這些習題進行解答
2 基礎
2.1 在Scala REPL中鍵入3,然後按Tab鍵。有哪些方法可以被應用?
這個。。。。直接操作一遍就有結果了.此題不知是翻譯的問題,還是原題的問題,在Scala REPL中需要按3. 然後按Tab才會提示。 直接按3加Tab是沒有提示的。下面是結果
Scala程式碼
1.!= ## % & * +
2.- / < << <= ==
3.> >= >> >>> ^ asInstanceOf
4.equals getClass hashCode isInstanceOf toByte toChar
5.toDouble toFloat toInt toLong toShort toString
6.unary_+ unary_- unary_~ |
列出的方法並不全,需要查詢全部方法還是需要到Scaladoc中的Int,Double,RichInt,RichDouble等類中去檢視。
2.2 在Scala REPL中,計算3的平方根,然後再對該值求平方。現在,這個結果與3相差多少?(提示:res變數是你的朋友)
依次進行計算即可
Scala程式碼
1.scala> scala.math.sqrt(3)
2.warning: there were 1 deprecation warnings; re-run with -deprecation for details
3.res5: Double = 1.7320508075688772
4.
5.scala> res5*res5
6.res6: Double = 2.9999999999999996
7.
8.scala> 3 - res6
9.res7: Double = 4.440892098500626E-16
2.3 res變數是val還是var?
val是不可變的,而var是可變的,只需要給res變數重新賦值就可以檢測res是val還是var了
Scala程式碼
1.scala> res9 = 3
2.<console>:8: error: reassignment to val
3. res9 = 3
4. ^
2.4 Scala允許你用數字去乘字串—去REPL中試一下"crazy"*3。這個操作做什麼?在Scaladoc中如何找到這個操作?
Scala程式碼
1.scala> "crazy"*3
2.res11: String = crazycrazycrazy
從程式碼可以推斷,*是"crazy"這個字串所具有的方法,但是Java中的String可沒這個方法,很明顯。此方法在StringOps中。
2.5 10 max 2的含義是什麼?max方法定義在哪個類中?
直接在REPL中執行
Scala程式碼
1.scala> 10 max 2
2.res0: Int = 10
3.
4.scala> 7 max 8
5.res1: Int = 8
6.
7.scala> 0 max 0
8.res2: Int = 0
可以看出,此方法返回兩個數字中較大的那個。此方法Java中不存在,所以在RichInt中。
2.6 用BigInt計算2的1024次方
簡單的API呼叫
Scala程式碼
1.scala> BigInt(2).pow(1024)
2.res4: scala.math.BigInt = 1797693134862315907729305190789024733617976978942306572734300811577326758055009631327084773224
3.075360211201138798713933576587897688144166224928474306394741243777678934248654852763022196012460941194530829520850057688
4.38150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137216
2.7 為了在使用probablePrime(100,Random)獲取隨機素數時不在probablePrime和Radom之前使用任何限定符,你需要引入什麼?
so easy. import需要的包啊。Random在scala.util中,而probablePrime是BigInt中的方法,引入即可
Scala程式碼
1.import scala.math.BigInt._
2.import scala.util.Random
3.
4.probablePrime(3,Random)
2.8 建立隨機檔案的方式之一是生成一個隨機的BigInt,然後將它轉換成三十六進位制,輸出類似"qsnvbevtomcj38o06kul"這樣的字串。
查閱Scaladoc,找到在Scala中實現該邏輯的辦法。 到BigInt中查詢方法。
Scala程式碼
1.scala> scala.math.BigInt(scala.util.Random.nextInt).toString(36)
2.res21: String = utydx
2.9 在Scala中如何獲取字串的首字元和尾字元?
Scala程式碼
1.//獲取首字元
2."Hello"(0)
3."Hello".take(1)
4.//獲取尾字元
5."Hello".reverse(0)
6."Hello".takeRight(1)
2.10 take,drop,takeRight和dropRight這些字串函式是做什麼用的?和substring相比,他們的優點和缺點都是哪些?
查詢API即可 take是從字串首開始獲取字串,drop是從字串首開始去除字串。 takeRight和dropRight是從字串尾開始操作。
這四個方法都是單方向的。 如果我想要字串中間的子字串,那麼需要同時呼叫drop和dropRight,或者使用substring
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
第二章 控制結構和函式
2.1 條件表示式
if(x > 0) 1 else -1
val s = if(x > 0) 1 else -1
混合型表示式:
if(x>0) "positive" else -1
2.2 語句終止
val n = 12
if(n>0) { r = r * n; n -= 1}
s = s0 + (v - v0) * t + 0.5 * (a-a0) * t * t
if(n > 0){
r = r * n
n -= 1
}
2.3 塊表示式和賦值
val distance = { val dx = x - x0; val dy = y - y0; sqrt(dx * dx + dy * dy)}
{ r = r * n; n -= 1}
2.4 輸入和輸出
print("Answer: ")
println(42)
println("Answer: " + 42)
println("Hello,%s! You are %d years old.\n","Fred",42)
val name = readLine("Your name: ")
print("Your age: ")
val age = readInt()
printf("Hello, %s! Next year,your will be %d.\n",name,age + 1)
2.5 迴圈
while(n > 0){
r = r * n
n -= 1
}
2.6 高階for迴圈和for推導式
for(i <- 1 to 3; j <- 1 to 3) print((10 * i + j) + " ")
for(i <- -1 to 3;j <- 1 to 3 if i != j) print((10 * i + j) + " ")
for(i <- 1 to 3; from = 4 - i;j <- from to 3) print((10 * i + j) + " ")
for(i <- 1 to 10 yield i % 3)
for(c <- "Hello"; i<- 0 to 1) yield (c + i).toChar
for(i <- 0 to 1;c <- "Hello") yield (c + i).toChar
for{ i<- 1 to 3
from = 4 -i
j <- from to 3
}
2.7 函式
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
}
對於遞迴函式,我們必須指定返回型別。例如:
def fac(n: Int): Int = if (n <= 0) 1 else n * fac(n - 1)
2.8 預設引數和帶名引數
def decorate(str: String,left: String = "[",right: String = "]") = left + str + right
decorate(left = "<<<",str = "Hello", right = ">>>")
decorate("Hello",right = "]<<<")
2.9 變長引數
def sum(args: Int*) = {
var result = 0
for(arg <- args) result += arg
result
}
val s = sum(1,4,9,16,25)
val s = sum(1 to 5)
val s = sum(1 to 5: _*)
def recursiveSum(args: Int*): Int = {
if(args.length == 0) 0
else args.head + recursiveSum(args.tail: _*)
}
val str = MessageFormat.format("The answer to {0} is {1}")
2.10 過程
Scala 對於不返回值的函式有特殊的表示法。如果函式體包含在花括號當中但沒有前面的=號,那麼返回型別就是Unit。
這樣的函式被稱做過程(procedure)。過程不返回值,我們呼叫它僅僅是為了它的副作用。舉例來說,如下過程把一個字串列印在一個框中,就像這樣:
--------
|hello|
--------
由於過程不返回任何值,所以我們可以略去=號
def box(s: String){
var border = "-" * s.length + "--\n"
println(border + "|" + s + "|\n" + border)
}
顯示宣告Unit返回型別
def box(s: String): Unit={
var border = "-" * s.length + "--\n"
println(border + "|" + s + "|\n" + border)
}
2.11 懶值
當val被宣告為lazy時,它的初始化將被推遲,直到我們首次對它取值。例如,
lazy val words = scala.io.Source.fromFile("/usr/share/dict/words").mkString
懶值對於開銷較大的初始化語句而言十分有用。它們還可以應對其他初始化問題,比如迴圈依賴。
你可以把懶值當做是介於val和def的中間狀態。對比如下定義:
//在worlds被定義時被取值
val words = scala.io.Source.fromFile("/usr/share/dict/words").mkString
//在words被首次使用時取值
lazy val words = scala.io.Source.fromFile("/usr/share/dict/words").mkString
//在每一次words被使用時取值
def words = scala.io.Source.fromFile("/usr/share/dict/words").mkString
2.12 異常
Scala異常工作機制和Java或C++一樣
throws new IllegalArgumentException("x should not be negative")
if(x >= 0){
sqrt(x)
} else throw new IllegalArgumentException("x should not be negative")
捕獲異常的語法採用的是模式匹配
try{
process(new URL("http://horstmann.com/fred-tiny.gif"))
} catch{
case _: MalformedURLException => println("Bad URL:" + url)
case ex: IOException => ex.printStackTrace()
}
var in = new URL("http://horstman.com/fred.gif").openStream()
try{
process(in)
} finally {
in.close()
}
try{...} catch{...} finally{...}
try{try{...} catch{...}} finally {...}
習題:
2 控制結構和函式
2.1 一個數字如果為正數,則它的signum為1;如果是負數,則signum為-1;如果為0,則signum為0.編寫一個函式來計算這個值
簡單的邏輯判斷
def signum(num:Int){if(num>0)print(1)else if(num<0)print(-1)else print(0)}
Scala中已經有此方法了,剛才查詢API的時候,應該能看到
BigInt(10).signum
2.2 一個空的快表示式{}的值是什麼?型別是什麼?
在REPL中就能看出來了
scala> val t = {}
t: Unit = ()
可以看出,它的值是()型別是Unit
2.2 指出在Scala中何種情況下賦值語句x=y=1是合法的。(提示:給x找個合適的型別定義)
題目已經給了明確的提示了。本章節中已經說過了,在scala中的賦值語句是Unit型別。所以只要x為Unit型別就可以了。
scala> var y=4;
y: Int = 4
scala> var x={}
x: Unit = ()
scala> x=y=7
x: Unit = ()
這也再次證明了{}是Unit型別
2.4 針對下列Java迴圈編寫一個Scala版本:
for(int i=10;i>=0;i–)
System.out.println(i);
使用Scala版本改寫就OK了
for(i <- 0 to 10 reverse)print(i)
2.5 編寫一個過程countdown(n:Int),列印從n到0的數字
這個就是將上面的迴圈包裝到過程中而已。還是換個寫法吧。
def countdown(n:Int){
0 to n reverse foreach print
}
2.6 編寫一個for迴圈,計算字串中所有字母的Unicode程式碼的乘積。舉例來說,"Hello"中所有字串的乘積為9415087488L
scala> var t:Long = 1
t: Long = 1
scala> for(i <- "Hello"){
| t = t * i.toLong
| }
scala> t
res57: Long = 9415087488
2.7 同樣是解決前一個練習的問題,但這次不使用迴圈。(提示:在Scaladoc中檢視StringOps)
scala> var t:Long = 1
t: Long = 1
scala> "Hello".foreach(t *= _.toLong)
scala> t
res59: Long = 9415087488
2.8 編寫一個函式product(s:String),計算前面練習中提到的乘積
def product(s:String):Long={
var t:Long = 1
for(i <- s){
t *= i.toLong
}
t
}
2.9 把前一個練習中的函式改成遞迴函式
配合前一章的take和drop來實現
def product(s:String):Long={
if(s.length == 1) return s.charAt(0).toLong
else s.take(1).charAt(0).toLong * product(s.drop(1))
}
2.10 編寫函式計算xn,其中n是整數,使用如下的遞迴定義:
•xn=y2,如果n是正偶數的話,這裡的y=x(n/2)
•xn = x*x(n-1),如果n是正奇數的話
•x0 = 1
•xn = 1/x(-n),如果n是負數的話
不得使用return語句
def mi(x:Double,n:Int):Double={
if(n == 0) 1
else if (n > 0 && n%2 == 0) mi(x,n/2) * mi(x,n/2)
else if(n>0 && n%2 == 1) x * mi(x,n-1)
else 1/mi(x,-n)
}
第3章 陣列相關操作
本章重點包括:
若長度固定則使用Array,若長度可能有變化則使用ArrayBuffer
提供初始值時不要使用new。
用()來訪問元素。
用for(elem <- arr)來遍歷元素
用for(elem <- arr if ...)...yield...來將原陣列轉型為新陣列
Scala陣列和Java陣列可以互操作;用ArrayBuffer,使用scala.collection.JavaConversions中的轉換函式。
3.1 定長陣列
val nums = new Array[Int](10)
val a = new Array[String](10)
val s = Array("Hello","World")
s(0) = "Goodbye"
在JVM中,Scala的Array以Java陣列方式實現。
示例中的陣列的JVM中的型別為java.lang.String[].Int、Double或其他與Java中基本型別對應的陣列都是基本型別陣列。舉例來說,Array(2,3,5,7,11)
3.2 變長陣列:陣列快取
import scala.collection.mutable.ArrayBuffer
val b = ArrayBuffer[Int]()
b += 1
b += (1,2,3,5)
//++=操作符追加任何集合
b ++= Array(8,13,21)
//移除最後5個元素
b.trimEnd(5)
//在下標2之前插入
b.insert(2,6)
//可以插入任意多的元素
b.insert(2,7,8,9)
b.remove(2)
b.remove(2,3)
//構建一個數組緩衝然後呼叫
b.toArray
//將陣列a轉換成一個數組緩衝
a.toBuffer
3.3 遍歷陣列和陣列緩衝
for(i <- 0 until b.length)
println(i + ": " + b(i))
//util是RichInt類的方法,返回所有小於上限的數字。
0 until 10
0 until (b.length,2)
(0 until b.length).reverse
for(elem <- a)
println(elem)
3.4 陣列轉換
val a = Array(2,3,5,7,11)
val result = for(elem <- a) yield 2 * elem
for(elem <- a if elem % 2 == 0) yield 2 * elem
a.filter(_ % 2 == 0).map(2 * _)
a.filter{ _ % 2 == 0} map { 2 * _}
var first = true
var n = a.length
var i = 0
while(i < 0){
if(a(i) >= 0) i+=1
else
if(first){first = false; i += 1}
else {a.remove(i);n -= 1}
}
var first = true
val indexes = for(i <- 0 until a.length if first || a(i) >= 0) yield{
if (a(i) < 0) first = false;
i
}
for(j <- 0 until indexes.length) a(j) = a(indexes(j))
a.trimEnd(a.length - indexes.length)
3.5 常用演算法
Array(1,7,2,9).sum
ArrayBuffer("Mary","had","a","little","lamb").max
val b = ArrayBuffer(1,7,2,9)
val bSorted = b.sorted(_ < _)
val bDescending = b.sorted(_ > _)
val a = Array(1,7,2,9)
scala.util.Sorting.quickSort(a)
a.mkString(" and ")
a.mkString("<",",",">")
a.toString
b.toString
3.6 解讀Scaladoc
3.7 多維陣列
val matrix = Array.ofDim[Double](3,4)
matrix(row)(column) = 42
val triangle = new Array[Array[Int]](10)
for(i <- until triangle.length)
triangle(i) = new Array[Int](i + 1)
3.8 與Java的互操作
import scala.collection.JavaConversions.bufferAsJavaList
import scala.collection.mutable.ArrayBuffer
val command = ArrayBuffer("ls","-a","/home/cay")
val pb = new ProcessBuilder(command)
import scala.collection.JavaConversions.asScalaBuffer
import scala.collection.mutable.Buffer
val cmd: Buffer[String] = pb.command()
1、編寫一段程式碼,將a設定為一個n個隨機整數的陣列,要求隨機數介於0(包含)和n(不包含)之間。
2、編寫一個迴圈,將整數陣列中相鄰的元素置換。例如,Array(1,2,3,4,5)經過置換後變為Array(2,1,4,3,5)
3、重複前一個練習,不過這一次生成一個新的值交換過的陣列。用for/yield
4、給定一個整數陣列,產生一個新的陣列,包含元陣列中的所有正值,以原有順序排列,之後的元素是所有零或負值,以原有順序排序
5、如何計算Array[Double]的平均值?
6、如何重新組織Array[Int]的元素將它們以反序排序?對於ArrayBuffer[Int]你又會怎麼做呢?
7、
第4章 對映和元組
4.1 構造對映
4.2 獲取對映中的值
4.3 更新對映中的值
4.4 迭代對映
4.5 已排序對映
4.6 與Java的互操作
4.7 元組
對映是鍵/值對偶的集合。對偶是元組的最簡單形式--元組是不同型別的值得聚集。
元組的值是通過將單個的值包含在圓括號中構成。例如:
(1,3,14,"Fred")
Tuple3[Int,Double,java.lang.String]
(Int,Double,java.lang.String)
val t = (1,3,14,"Fred")
val secnd = t._2
通常,使用模式匹配來獲取元組的組元,例如:
val (first,second,third) = t //將first設為1,second設為3.14,third設為"Fred"
val (first,second, _) = t
"New York".partition(_.isUpper)
4.8 拉鍊操作
val symbols = Array("<","-",">")
val counts = Array(2,10,2)
val pairs = symbols.zip(counts)
本章的要點包括:
Scala有十分易用的語法來建立、查詢和遍歷對映。
你需要從可變的和不可變的對映中做出選擇。
預設情況下,你得到的是一個雜湊對映,不過你也可以指明要樹形對映。
你可以很容易地在Scala對映和Java對映之間來回切換。
元組可以用來聚集值
4.1 構造對映
val scores = Map("Alice" -> 10,"Bob" -> 3,"Cindy" -> 8)
val scores = scala.collection.mutable.Map("Alice" -> 10,"Bob" -> 3,"Cindy" -> 8)
val scores = new scala.collection.mutable.HashMap[String,Int]
->操作符用來建立對偶
"Alice" -> 10
上述程式碼產出的值:
()
1、設定一個對映,其中包含你想要的一些裝備,以及它們的價格。然後構建另一個對映,採用用一組鍵,但在價格上9折
2、編寫一段程式,從檔案中讀取單詞。用一個可變對映來清點每一個單詞出現的頻率。讀取這些單詞的操作可以使用java.util.Scanner:
val in = new java.util.Scanner(new java.io.File("myfile.txt"))
while(in.hasNext()) 處理 in.next()
最後,打印出所有單詞和它們出現的次數
3、重複前一個練習,這次用不可變的對映。
4、重複前一個練習,這次用已排序的對映,以便單詞可以按順序打印出來。
5、重複前一個練習,這次用java.util.TreeMap並使之適用於Scala API
6、定義一個鏈式雜湊對映,將“Monday”對映到java.util.Calendar.MONDAY,依次類推加入其他日期。展示元素是以插入的順序被訪問的。
7、打印出所有Java系統屬性的表格,類似這樣:
java.runtime.name | Java(TM) SE Runtime Environment
sun.boot.library.path | /home/apps/jdk1.6.0.21/jre/lib/i386
java.vm.version | 17.0-bl6
java.vm.vendor | Sun Microsystems Inc
java.vendor.url | http://java.sun.com/
path.separator | :
java.vm.name | Java HotSpot(TM) Server VM
8、編寫一個函式
9、編寫一個函式
10、當你將兩個字串拉鍊在一起,比如
11、
第5章
5.1 簡單類和無參方法
class Counter{
private var value = 0 //
def increment(){ value += 1}
def current() = value
}
val myCounter = new Counter
myCounter.increment()
println(myCounter.current)
myCounter.current
myCounter.current()
5.2 帶getter和setter的屬性
5.3 只帶getter的屬性
5.4 物件私有欄位
5.5 Bean屬性
import scala.reflect.BeanProperty
class Person{
@BeanProperty var name: String = _
}
將會生成四個方法:
1、name: String
2、name_=(newValue:String):Unit
3、getName():String
4、setName(newValue:String):Unit
class Person(@BeanProperty var name: String)
5.6 輔助構造器
class Person{
private var name = ""
private var age = 0
def this(name: String){
this()
this.name = name
}
def this(name: String,age: Int){
this(name)
this.age = age
}
}
val p1 = new Person
val p2 = new Person("Fred")
val p3 = new Person("Fred",42)
5.7 主構造器
class Person(val name: String,val age: Int){
}
5.8 巢狀類
import scala.collection.mutable.ArrayBuffer
class Network{
class Member(val name: String){
val contacts = new ArrayBuffer[Member]
}
private val members = new ArrayBuffer[Member]
def join(name: String) = {
val m = new Member(name)
members += m
m
}
}
val chstter = new Network
val myFace = new Network
val fred = chatter.join("Fred")
val wilma = chatter.join("Wilma")
fred.contacts += wilma
val barney = myFace.join("Barney")
fred.contacts += barney
object Network{
class Member(val name: String){
val contacts = new ArrayBuffer[Member]
}
}
class Network{
private val members = new
}
第七章 包和引入
7.1 包
package com{
package horstman{
package impattern{
class Employee
}
}
}
package org{
package bigjava{
class Counter
}
}
7.2 作用域規則
package com{
package horstmann{
object Utils{
def percentOf(value: Double,rate: Double) = value * rate / 100
...
}
}
}
package impatient{
class Employee{
def giveRaise(rate: scala.Double){
salary += Utils.percentOf(salary,rate)
}
}
}
7.3 串聯式包語句
7.4 檔案頂部標記法
7.5 包物件
7.6 包可見性
7.7 引入
7.8 任何地方都可以宣告引入
7.9 重新命名和隱藏方法
import java.awt.{Color,Font}
import java.util.{HashMap => JavaHashMap}
import scala.collection.mutable._
import java.util.{HashMap => _,_}
import scala.collection.mutable._
7.10 隱式引入
import java.lang._
import scala._
import Predef._
collection.mutable.HashMap
scala.collection.mutable.HashMap
第8章 繼承
8.1 擴充套件類
class Employee extends Person{
var salary = 0.0
}
8.2 重寫方法
public class Person{
override def toString = getClass.getName + "[name=" + name + "]"
}
8.3 型別檢查和轉換
if(p.isInstanceOf[Employee]){
val s = p.asInstanceOf[Employee]
}
8.4 受保護欄位和方法
8.5 超類的構造
8.6 重寫欄位
8.7 匿名子類
8.8 抽象類
8.9 抽象欄位
8.10 構造順序和提前定義
8.11 Scala繼承層級
8.12 物件相等性