scala基础-1
函数式编程
并行编程
多核计算、云计算
引用透明,给值确定,结果也确定
数据类型
三种变量修饰符
val 定义immutable variable
var 定义mutable variable
lazy val
可以不显示指定变量的类型,因为scala会自动进行类型推导
默认变量名 res
val 定义的值不可改变
根类Any
二层:AnyVal、AnyRef
AnyVal=>Numeric types、Boolean、Char、Unit
AnyRef=>All java.* ref types、All scala.* ref types=>Null
String
scala> val myname="zzd"
myname: String = zzd
scala> s"my name is ${myname}"
res7: String = my name is zzd
函数与代码块
scala语言支持:
- 把函数作为实参传递给另外一个函数
- 把函数作为返回值
- 把函数赋值给变量
- 把函数存储在数据结构里
scala中,函数就像变量一样,同样也具有函数的类型
函数类型
函数类型的格式:A=>B 表示一个接受类型A的参数,并返回类型B的函数 Int=>String 把整型映射为字符串的函数类型
Block
{exp1;exp2}
{
exp1
exp2
}
Block也是一个表达式,其最终的值是最后一个表达式的值
Function
def functionNmae(param:paramType):ReturnType={//function body}
example:
def hello(name: String): String = {
s"Hello,${name}"
} //> hello: (name: String)String
hello("zzd") //> res0: String = Hello,zzd
def hello2(name: String) = {
s"Hello,${name}"
} //> hello2: (name: String)String
hello2("zzd") //> res1: String = Hello,zzd
def add(x:Int,y:Int)=x+y //> add: (x: Int, y: Int)Int
add(2,3)
if表达式
if(logical_exp) valA else valB
example:
val a = 1 //> a : Int = 1
if (a == 1) a //> res5: AnyVal = 1
if (a != 1) "not one" //> res6: Any = ()
if (a != 1) "not one" else a //> res7: Any = 1
for comprehension
for{
x<-xs
y=x+1
if(y>0)
}yield y
val l = List("alice", "bob", "cathy") //> l : List[String] = List(alice, bob, cathy)
for (
s <- l //generator 遍历l赋值给s
)
println(s) //> alice
//| bob
//| cathy
for {
s <- l
if (s.length > 3)
} println(s) //> alice
//| cathy
var result_for = for {
s <- l
s1 = s.toUpperCase()
if (s1 != "")
} yield (s1) //> result_for : List[String] = List(ALICE, BOB, CATHY) }
try表达式
try{}
catch{}
finally{}
try{
Integer.parseInt("dog")
}catch{
case _ =>0
}finally{
println("always be printed")
}
match表达式
exp match{//主要用在pattern match中
case p1 => val1
case p2 => val2
...
case _ => valn
}
val code = 2 //> code : Int = 2
code match{
case 1 => "one"
case 2 => "two"
case _ => "others"
} //> always be printed
//| res9: Int = 0
匿名函数
anonymous function 就是函数变量,也称为函数文字量
定义格式:(形参列表) => {函数体}
柯里化
柯里化函数(curried function)把具有多个参数的函数转换为一条函数链,每个节点上是单一参数
def add(x: Int,y: Int) = x+y
def add(x: Int)(y: Int) = x+y
def curriedAdd(a:Int)(b:Int)=a+b //> curriedAdd: (a: Int)(b: Int)Int
val addOne=curriedAdd(1)_ //> addOne : Int => Int = <function1>
addOne(2)
递归函数
栗子:计算n!
def factorial(n:Int):Int=
if(n<=0) 1
else n*factorial(n-1)
尾递归函数
尾递归函数中所有递归形式的调用都放在函数的末尾。当编译器检测到一个函数调用是尾递归的时候,它就覆盖当前的活动记录而不是在栈中去创建一个新的。
算子
reduceLeft & foldLeft
reduceLeft
基础语法
reduceLeft( op: (T,T) => T)
a.reduceLeft((x,y) => x+y)
a.reduce(_+_) //a=List(1,2,3,4),10
foldLeft
基础语法
foldLeft(Z : U)(op : (U,T) => U)
a.foldLeft(0)(_+_) //将a的每个元素相加后加0
a.foldLeft(1)(_*_) //将a的每个元素相乘后乘1
Range & Stream
Range
1 to 10 //List(1,2,3,4,5,6,7,8,9,10)
1 util 10 //List(1,2,3,4,5,6,7,8,9)
1 to 10 by 2 //List(1,3,5,7,9)
Stream
lazy list
scala> val s= 1#::2#::3#::Stream.empty
s: scala.collection.immutable.Stream[Int] = Stream(1, ?)
scala> val stream=(1 to 1000000).toStream
stream: scala.collection.immutable.Stream[Int] = Stream(1, ?)
scala> stream.head
res30: Int = 1
scala> stream.tail
res31: scala.collection.immutable.Stream[Int] = Stream(2, ?)
toupe & map
toupe
scala> (1,"Alice","Math",95.5)
res34: (Int, String, String, Double) = (1,Alice,Math,95.5)
scala> val t=(1,"Alice","Math",95.5)
t: (Int, String, String, Double) = (1,Alice,Math,95.5)
scala> t._1
res35: Int = 1
scala> t._3
res36: String = Math
scala> def sumSq(in : List[Int]):(Int,Int,Int)=
| in.foldLeft((0,0,0))((t,v) => (t._1,t._2+v,t._3+v*v))
sumSq: (in: List[Int])(Int, Int, Int)
scala> sumSq(a)
res37: (Int, Int, Int) = (0,10,30) //a:List(1,2,3,4)
Map[K,V]
scala> val p=Map(1 -> "David",9 -> "Elwood") //定义map键值对
p: scala.collection.immutable.Map[Int,String] = Map(1 -> David, 9 -> Elwood)
scala> p(1) //获取p的key所对应的value
res40: String = David
scala> p(9)
res41: String = Elwood
scala> p.contains(1) //判断是否存在key为1
res42: Boolean = true
scala> p.keys //获取p的所有key
res43: Iterable[Int] = Set(1, 9)
scala> p.values //获取p的所有值
res44: Iterable[String] = MapLike.DefaultValuesIterable(David, Elwood)
scala> p+(8 -> "Archer") //在p中增加一组键值对
res45: scala.collection.immutable.Map[Int,String] = Map(1 -> David, 9 -> Elwood, 8 -> Archer)
scala> p-1 //减少p中的一组键值对
res47: scala.collection.immutable.Map[Int,String] = Map(9 -> Elwood)
scala> p ++ List(2 -> "Alice",5 -> "Bob") //在p中增加多组键值对
res49: scala.collection.immutable.Map[Int,String] = Map(1 -> David, 9 -> Elwood, 2 -> Alice, 5 -> Bob)
scala> p -- List(1,2,9) //减少p中的多组键值对
res50: scala.collection.immutable.Map[Int,String] = Map()
scala> p ++ List(2 -> "Alice",5 -> "Bob") -- List(1,2,9)
res51: scala.collection.immutable.Map[Int,String] = Map(5 -> Bob)
scala.collection.immutable
List[T]
基础语法:
val a=List(1,2,3,4)
val b=0::a //::是连接符,将0插入到a的头部,b=List(0,1,2,3,4)
val c="x"::"y"::"z"::Nil //c:List(String)=List(x,y,z)
val s=a:::c //:::List合并符,s:List[Any]=List(1,2,3,4,x,y,z)
a.head //1,输出list的第一个元素
a.tail //2,3,4 输出list中除第一个以外的其他元素
a.filter(x => x % 2 == 1)
a.filter(_ % 2 == 1) //List(1,3),保留奇数
"99 Red Balloons".toList //将字符串的每一个字符提取出来放到一个List里,List[Char] = List(9, 9, , R, e, d, , B, a, l, l, o, o, n, s)
"99 Red Balloons".toList.filter(x => Character.isDigit(x)) //List[char]=List(9,9)
"99 Red Balloons".toList.takeWhile(x => x!='B') //List[char]=List(9,9, ,R,e,d, )
遍历list
def walthru(l:List[Int]):String={
if(l.isEmpty) ""
else l.head.toString+" "+walkthru(l.tail)
}
walkthru(s) //String="1 2 3 4 "
list-map
c.map(x => x.toUpperCase)
c.map(_.toUpperCase) //List[String]=List(X,Y,Z),传入列表中的每个元素
val q=List(a,List(4,5,6))
q.map(x => x.filter( _ % 2 == 0))
q.map( _.filter( _ % 2 == 0) ) //筛选出所有偶数,List(List(2,4),List(4,6))
q.flatMap( _.filter( _ % 2 == 0) ) //List(2,4,,4,6),将两层的list合并成一层的list
函数式集合
1.Scala中的集合体系主要包括:Iterable、Seq(IndexSeq)、Set(SortedSet)、Map(SortedMap)。其中Iterable是所有集合trait的根trait。实际上Seq、Set、和Map都是子trait
Seq:是一个有先后次序的值的序列,比如数组或列表。IndexSeq允许我们通过整形的下表快速的访问任意元素。举例来说,ArrayBuffer是带下标的,但是链表不是。
Set:是一组没有先后次序的值。在SortedSet中,元素以某种排过序顺序被访问。
Map:是一组(键、值)对偶。SortedMap按照键的排序访问其中的实体。
2.Scala中的集合是分成可变和不可变两类集合的,其中可变集合就是说,集合的元素可以动态修改,而不可变集合的元素在初始化之后,就无法修改了。分别对应scala.collection.mutable和scala.collection.immutable两个包。
3.Seq下包含了Range、ArrayBuffer、List等子trait。其中Range就代表了一个序列,通常可以使用“1 to 10”这种语法来产生一个Range。 ArrayBuffer就类似于Java中的ArrayList。
List
方法 | 描述 |
---|---|
head | 此方法返回的列表中的第一个元素。 |
tail | 此方法返回一个由除了第一个元素外的所有元素的列表。 |
isEmpty | 如果列表为空,此方法返回true,否则为false。 |
::操作符从给定的头和尾部创建一个新的列表
def dynamicListOps: Unit ={
// List of Strings
val fruit = "apples" :: ("oranges" :: ("pears" :: Nil))
fruit.foreach(println(_))
}
list求和
println(List(9,4,2).sum)
linkedList
可变的LinkedList和不可变的List相似,只不过你可以通过对elem引用赋值来修改其头部,对next引用赋值来修改其尾部。
def linkedListOps: Unit ={
val lst = scala.collection.mutable.LinkedList(1,-2,7,-9)
var cur = lst
while(cur != Nil){
if(cur.elem < 0) cur.elem = 0
cur = cur.next
}
lst.foreach(println(_))
}
set
1、集是不重复元素的集合。尝试将已有元素加入进来是没有效果的。比如
def setOps: Unit ={
(Set(2,0,1) + 1).foreach(println(_))
}
2、Set不保留元素插入的顺序。缺省情况下,集市以哈希集实现的,其元素根据hashCode方法的值进行组织。
Set(1,2,3,5,7,8).foreach(println(_))
3、链式哈希集可以记住元素被插入的顺序。它会维护一个链表来达到这个目的。
val weeks = scala.collection.mutable.LinkedHashSet("Mo","Tu","We","Th","Fr")
weeks.foreach(println(_))
4、按照已排序的顺序来访问其中的元素
scala.collection.immutable.SortedSet(1,2,3,4,5,6).foreach(println(_))
模式匹配
模式匹配
- 模式匹配==》可以用到Switch语句中
- 模式匹配==》守卫
- 模式匹配==》模式中的变量
- 模型匹配==》类型模式
- 模式匹配=》匹配数组、列表和元组
- 模式匹配==》样例类
- 模式匹配==》Copy方法和带名参数
- 模式匹配==》模拟枚举
- 模式匹配==》Option
1、可以用到Switch语句中
def swithOps: Unit ={
var sign = 0
val ch: Char = '+'
ch match {
case '+' => sign = 1
case '-' => sign = -1
case _ => sign = 0
}
println("sign===> " + sign)
}
match是表达式,不是语句,所以是有返回值的,故可将代码简化:
sign = ch match {
case '+' => 1
case '-' => -1
case _ => 0
}
println("sign=====> "+ sign)
def ifSafeOps: Unit ={
var sign = 0
val ch: Char = '1'
val result = ch match {
case '+' => sign = 1
case '-' => sign = -1
case _ if Character.isDigit(ch) => 3
case _ => sign = 0
}
println(result)
}
2、守卫
def ifSafeOps: Unit ={
var sign = 0
val ch: Char = '1'
val result = ch match {
case '+' => sign = 1
case '-' => sign = -1
case _ if Character.isDigit(ch) => 3
case _ => sign = 0
}
println(result)
}
3、如果在case关键字后跟着一个变量名,那么匹配的表达式会被赋值给那个变量。case _
是这个特性的一个特殊情况,变量名是_。
def patternOps ={
"Hello, world" foreach { c => println (
c match {
case ' ' => "space"
case ch => "Char: " + ch
}
)}
}
4、类型模式
/**
* 类型匹配 Any:(Int, String,)
*/
def typeOps(x:Any):Int = {
val result = x match {
case i:Int => i
case s:String => Integer.parseInt(s)
case z:scala.math.BigInt => Int.MaxValue
case c:Char => c.toInt
case _ => 0
}
result
}
def verifyTypeOps: Unit ={
println( typeOps("12333"))
}
5、匹配数组、列表和元组
def arrayOps: Unit ={
val arr = Array(0,0.1)
arr match {
case Array(0) => println("0" ) // 匹配包含0的数组
case Array(x, y) =>println( x + " " + y ) // 匹配任何带有两个元素的数组,并将元素绑定到x和y
case Array(0, _*) => println("0 ..." ) // 匹配任何以0开始的数组
case _ => println("something else")
}
}
6、样例类
abstract class Expr
case class Var(name:String) extends Expr
case class Number(num:Double) extends Expr
case class UnOp(operator : String , arg : Expr) extends Expr
case class BinOp(operator : String , left : Expr , right : Expr) extends Expr
def simplifyTop(expr : Expr) : Expr = expr match{
case UnOp("-" , UnOp("-" , e)) => e
case BinOp("+" , e , Number(0)) => e
case BinOp("*" , e , Number(1)) => e
case _ => expr
}
def verifyMatch: Unit ={
println(simplifyTop(Var("limu")))
}
未完待续......