Scala筆記學習之二


定義主函數

object HelloWorld {
def main(args: Array[String]) {
println("Hello, world!")
}
}
//交互式命令行調用
HelloWorld.main(null)

Scala代碼作為腳本語言

./hello.sh

#!/bin/sh
exec scala "$0" "$@"
!#
object HelloWorld extends App {
println("Hello, world!")
}
HelloWorld.main(null)

Scala解釋器命令

可以輸入任意的Scala表達式
在命令行中需要分多行輸入,Scala解釋器在新行前面顯示|

//退出
quit
//多行
val msg3=
| "Hello world 3rd time"

定義變量

Scala的“type inference”特點 ;類型推導-自動推測類型
val 類似於Java中的final 變量 不可以重新復制
var 可以任意重新賦值

//默認會自動推測類型
val msg="Hello,World"
//也可以定義類型
val msg1:String ="Hello again,world"
var msg2="Hello,World2"
msg2="haha"

定義函數

函數在Scala語言中的地位和類是同等第一位的
每個Scala表達式都有返回結果
函數的最后一個表達式的值就可以作為函數的結果作為返回值

def max(x:Int,y:Int) : Int ={
if (x >y) x
else
y
}
max(6,7)
def max2(x:Int,y:Int) : Int ={if (x >y) x else y}
max2(9,7)
//無返回值 顯示Unit相當於void
def greet() = println("hello,world")

while循環

scala不支持i++使用i+=1代替

var args="asdasdasd"
var i=0
while (i < args.length) {
println (args(i))
i+=1
}
#Scala訪問數組的語法是使用()

foreach 和 for 來實現迭代

采用“函數式”風格

args.foreach(arg => println(arg))
//簡寫
args.foreach( println)
//for
for (arg <-args)
println(arg)

初始化數組Array

Array可以修改內容

val greetStrings = new Array[String](3)
greetStrings(0)= "Hello"
greetStrings(1)= ","
greetStrings(2)= "world!\n"
for(i <- 0 to 2)
print(greetStrings(i))
//簡化
val greetStrings =Array("Hello",",","World\n")

Lists

Scala的Lists對象是不可修改的
List只能包含同類型的數據

val oneTwo = List(1,2)
val threeFour = List(3,4)
val oneTwoThreeFour=oneTwo ::: threeFour
println (oneTwo + " and " + threeFour + " were not mutated.")
println ("Thus, " + oneTwoThreeFour + " is a new list")

Scala 的List類 head、last、length、reverse、tail等

head、last、length、reverse、tail

oneTwoThreeFour.head list第一個元素
oneTwoThreeFour.last list最后一個元素
reverse反轉length長度
oneTwoThreeFour.tail 除去第一個的其他元素

:::連接兩個列表

::添加元素

//向List中添加一個元素
val oneTowThree = 1 :: 2 ::3 :: Nil
println(oneTowThree)

元組(Tuples)

Tuples可以包含不同類型的數據
返回多個結果時非常有用
對應到數學的矢量

//可以使用._索引 來訪問員組的元素,元組的索引從1開始
val pair=(99,"Luftballons")
println(pair._1)
println(pair._2)

Sets和Maps

set不可修改
map可修改

var jetSet = Set ("Boeing","Airbus")
//添加元素
jetSet +="Lear"
//判斷是否存在
println(jetSet.contains("Cessna"))

val romanNumeral = Map ( 1 -> "I" , 2 -> "II",
3 -> "III", 4 -> "IV", 5 -> "V")
println (romanNumeral(4))

函數編程風格

能不用vars,盡量不用vars,能不用mutable變量,盡量不用mutable變量,能避免函數的副作用,盡量不產生副作用。

//java風格不推薦
def printArgs ( args: Array[String]) : Unit ={
var i=0
while (i < args.length) {
println (args(i))
i+=1
}
}
//去var變量
def printArgs ( args: Array[String]) : Unit ={
for( arg <- args)
println(arg)
}
//更簡化
def printArgs ( args: Array[String]) : Unit ={
args.foreach(println)
}

讀取文件

import scala.io.Source
def readfile( args: String) : Unit ={
if (args.length >0 ){
for( line <- Source.fromFile(args).getLines())
println(line.length + " " + line)
}
else
Console.err.println("Please enter filename")
}
readfile("/Users/yuyin/Downloads/myfile/note/test.txt")

枚舉當前目錄下所有文件

val filesHere = (new java.io.File(".")).listFiles
for( file <-filesHere)
println(file)

類和對象的定義

以class 開始
缺省修飾符為public
Scala的方法的參數都是val類型,在函數體內不可以修改參數的值

class ChecksumAccumulator{
private var sum=0
def add(b:Byte) :Unit = sum +=b
def checksum() : Int = ~ (sum & 0xFF) +1
}
import scala.collection.mutable.Map
class ChecksumAccumulator{
private var sum=0
def add(b:Byte) :Unit = sum +=b
def checksum() : Int = ~ (sum & 0xFF) +1
}

object ChecksumAccumulator {
private val cache = Map [String, Int] ()
def calculate(s:String) : Int =
if(cache.contains(s))
cache(s)
else {
val acc=new ChecksumAccumulator
for( c <- s)
acc.add(c.toByte)
val cs=acc.checksum()
cache += ( s -> cs)
cs
}
}

println ( ChecksumAccumulator.calculate("Welcome to Scala Chinese community"))

控制語句if

//java風格
var filename="default.txt"
if(!args.isEmpty)
filename =args(0)
//scala風格
val filename=
if(!args.isEmpty) args(0)
else "default.txt"

for生成新集合

//生成Array[File]
def scalaFiles =
for {
file if file.getName.endsWith(".scala")
} yield file

用 try 表達式處理異常

val half =
if (n % 2 == 0)
n/2
else
throw new RuntimeException("n must be even")

import java.io.FileReader
import java.io.FileNotFoundException
import java.io.IOException
try {
val f = new FileReader("input.txt")
} catch {
case ex: FileNotFoundException => //handle missing file
case ex: IOException => //handle other I/O error
}

finally

通常情況下,finally塊用來做些清理工作,而不應該產生結果

import java.io.FileReader
val file = new FileReader("input.txt")
try {
//use the file
} finally {
file.close()
}

Match 表達式

Scala的缺省匹配為“_”

val firstArg = if (args.length >0 ) args(0) else ""
firstArg match {
case "salt" => println("pepper")
case "chips" => println("salsa")
case "eggs" => println("bacon")
case _ => println("huh?")
}

使用true判斷代替break與continue

var i=0
var foundIt=false
while (i < args.length && !foundIt) {
if (!args(i).startsWith("-")) {
if(args(i).endsWith(".scala"))
foundIt=true
}
i=i+1
}

遞歸函數重新實現上面代碼實現的查詢功能:

def searchFrom(i:Int) : Int =
if( i >= args.length) -1
else if (args(i).startsWith("-")) searchFrom (i+1)
else if (args(i).endsWith(".scala")) i
else searchFrom(i+1)
val i = searchFrom(0)

filter方法用來過濾集合中的元素

val someNumbers = List ( -11, -10, - 5, 0, 5, 10)
someNumbers.filter( x => x >0)
//Scala允許使用“占位符”下划線“_”來替代一個或多個參數,只要這個參數值函數定義中只出現一次,Scala編譯器可以推斷出參數
someNumbers.filter(_ >0)
//print _ 來代替 println (_)
someNumbers.foreach( x => println (x))
someNumbers.foreach(println _)

部分應用函數

一個部分應用的函數指的是你在調用函數時,不指定函數所需的所有參數

//固定sum的第一和第三個參數
def sum = (_:Int) + (_ :Int) + (_ :Int)
val b = sum ( 1 , _ :Int, 3)
b(2)

閉包

引用到函數外面定義的變量

var more =1
val addMore = (x:Int) => x + more
addMore (100)
more=11
addMore (100)

可變參數

“*”來指明該參數為重復參數 變長參數

//String * 類型實際為 Array[String]
def echo (args: String *) = for (arg <- args) println(arg)
echo("x")
echo("x","ss")

_* 在傳遞參數時,逐個傳入數組的每個元素

val arr= Array("What's","up","doc?")
echo (arr: _*)

柯里化函數(Currying)

柯里化是把接受多個參數的函數變換成接受一個單一參數(最初函數的第一個參數)的函數,並且返回接受余下的參數而且返回結果的新函數的技術。

//非柯里化
def plainOldSum(x:Int,y:Int) = x + y
plainOldSum(1,2)
//柯里化
def curriedSum(x:Int)(y:Int) = x + y
curriedSum (1)(2)

Scala的類層次關系

所有的類都繼承自Any,因此Scala中的對象都可以使用==、!=或equals來比較,使用##或hashCode給出hash值,使用 toString 轉為字符串。
AnyVal是Scala里每個內建值類型的父類。有九個這樣的值類型:Byte,Short,Char,Int,Long,Float,Double,Boolean和Unit
方法min、max、until、to和abs都定義在類scala.runtime.RichInt里,並且有一個從類Int到RichInt的隱式轉換。
AnyRef是Scala里所有引用類的基類,似java.lang.Object

Trait

集合了Interface和抽象類的優點,同時又沒有破壞單一繼承的原則
可以使用extends或with來混合一個trait

trait Philosophical{
def philosophize() {
println("I consume memeory, therefor I am!")
}
}
class Frog extends Philosophical{
override def toString="gree"
}
val frog = new Frog
frog.philosophize

注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com