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语言支持:

  1. 把函数作为实参传递给另外一个函数
  2. 把函数作为返回值
  3. 把函数赋值给变量
  4. 把函数存储在数据结构里

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")))
 }  

未完待续......

posted @ 2018-11-29 20:11  枫子_dan  阅读(182)  评论(0编辑  收藏  举报