scala基础语法

Scala学习笔记

  1. Note

(1)函数可作为一个参数传入到方法中,而方法不行。

scala基础语法_第1张图片

2、在Scala中无法直接操作方法,如果要操作方法,必须先将其转换成函数。有两种方法可以将方法转换成函数:

val f1 = m _

在方法名称m后面紧跟一个空格和下划线告诉编译器将方法m转换成函数,而不是要调用这个方法。也可以显示地告诉编译器需要将方法转换成函数:

object TestMap {

  def ttt(f:Int => Int):Unit = {

    val r = f(10)

    println(r)}

  val f0 = (x : Int) => x * x

  //定义了一个方法

  def m0(x:Int) : Int = {

    //传递进来的参数乘以10

    x * 10 }

  //将方法转换成函数,利用了神奇的下滑线

  val f1 = m0 _

  def main(args: Array[String]): Unit = {

    ttt(f0)

    //通过m0 _将方法转化成函数

    ttt(m0 _);

    //如果直接传递的是方法名称,scala相当于是把方法转成了函数

    ttt(m0)

    //通过x => m0(x)的方式将方法转化成函数,这个函数是一个匿名函数,等价:(x:Int) => m0(x)

    ttt(x => m0(x))  }}

输出结果为:

100

100

100

100

3、函数必须要有参数列表,而方法可以没有参数列表

scala基础语法_第2张图片

4、在函数出现的地方我们可以提供一个方法

scala基础语法_第3张图片

 

 

Scala的解释器在解析函数参数(function arguments)时有两种方式:

传值调用(call-by-value):先计算参数表达式的值,再应用到函数内部;

传名调用(call-by-name):将未计算的参数表达式直接应用到函数内部

在进入函数内部前,传值调用方式就已经将参数表达式的值计算完毕,而传名调用是在函数内部进行参数表达式的值计算的。

这就造成了一种现象,每次使用传名调用时,解释器都会计算一次表达式的值。

 

object ImplictClassDemo {

  def main(args: Array[String]) {

    delayed(time());}

  def time() = {

    println("获取时间,单位为纳秒")

    println("haha")

    System.nanoTime

  }

  def delayed( t: => Long ) = {

    println("在 delayed 方法内")

    println("xixix")

    println("参数: " + t)}}

程序运行结果:

delayed 方法内

xixix

获取时间,单位为纳秒

haha

参数: 3678564244605

object ImplictClassDemo {

  def main(args: Array[String]) {

    delayed(time());

  }

  def time() = {

    println("获取时间,单位为纳秒")

    println("haha")

    System.nanoTime

 }

  def delayed( t: => Long ) = {

    println("在 delayed 方法内")

    println("xixix")

    println("参数: " + t)    

    t 
}}

 

delayed 方法内

xixix

获取时间,单位为纳秒

haha

参数: 3775229046975

获取时间,单位为纳秒

Haha

 

object ImplictClassDemo {

  def main(args: Array[String]) {

    delayed(time());

  }

  def time() = {

    println("获取时间,单位为纳秒")

    println("haha")

    System.nanoTime

  }

  def delayed( t: => Long ) = {

    println("参数: " + t)

    println("在 delayed 方法内")

    println("xixix")

    println("参数: " + t)

  }

}

 

获取时间,单位为纳秒

haha

参数: 3950452511877

delayed 方法内

xixix

获取时间,单位为纳秒

haha

参数: 3950452676651

 

Scala 指定函数参数名

一般情况下函数调用参数,就按照函数定义时的参数顺序一个个传递。但是我们也可以通过指定函数参数名,并且不需要按照顺序向函数传递参数。

Scala 函数 - 可变参数

Scala 允许你指明函数的最后一个参数可以是重复的,即我们不需要指定函数参数的个数,可以向函数传入可变长度参数列表。

Scala 通过在参数的类型之后放一个星号来设置可变参数(可重复的参数)。例如:

scala基础语法_第4张图片

 

递归函数:

object Test {

   def main(args: Array[String]) {

      for (i <- 1 to 10)

         println(i + " 的阶乘为: = " + factorial(i) )

   }

  

   def factorial(n: BigInt): BigInt = { 

      if (n <= 1)

         1 

      else   

      n * factorial(n - 1)

   }

}

 

Scala 高阶函数

高阶函数(Higher-Order Function)就是操作其他函数的函数。Scala 中允许使用高阶函数, 高阶函数可以使用其他函数作为参数,或者使用函数作为输出结果。

object Test {
   def main(args: Array[String]) {
      println( apply( layout, 10) )
   }
   // 函数 f   v 作为参数,而函数 f 又调用了参数 v
   def apply(f: Int => String, v: Int) = f(v)
 
   def layout[A](x: A) = "[" + x.toString() + "]" 
}
 

匿名函数

Scala 中定义匿名函数的语法很简单,箭头左边是参数列表,右边是函数体。

使用匿名函数后,我们的代码变得更简洁了。

下面的表达式就定义了一个接受一个Int类型输入参数的匿名函数:

var inc = (x:Int) => x+1

上述定义的匿名函数,其实是下面这种写法的简写:

def add2 = new Function1[Int,Int]{ 

    def apply(x:Int):Int = x+1; 

}

我们也可以不给匿名函数设置参数,如下所示:

var userDir = () => { System.getProperty("user.dir") }

Option的类型是函数:

scala基础语法_第5张图片

scala基础语法_第6张图片

  1. scala特点

面向对象编程

函数式编程

静态类型语言

(动态类型语言如Python(变量a的数据类型在运行阶段确定)和静态类型语言如java scala(变量a的数据类型在编译阶段确定))

基于JVM(aa.scalaàaa.class-àJVM)

   学习scala原因:

  1. 速度快
  2. 优雅简洁
  3. 融入大数据生态圈,深入学习spark
  1. 变量

var 变量名=初始化值

var 变量名:数据类型=初始化值

注意:

  1. 定义变量的时候需要初始化
  2. 定义变量的时候可以不指定变量的数据类型,系统会根据变量的初始化值推断变量的数据类型。var a=1 或者var a:Int=1
  1. 常量

val 变量名=初始化值

val 变量名:数据类型=初始化值

注意:

val修饰的变量,相当于Javafinal修饰的变量

val修饰的变量,变量的类型是值类型(相当于java中的基本数据类型,int ,double,boolean),值是不可以修改的。

 val a=10

 a=100(错误不可修改)

val修饰的变量,变量的类型是引用类型,引用不可变,引用的内容可变

  val a1=Array(1,2,3)

  val a2=Array(4,5,6)

a1=a2  //不可以,引用不可变

a1(0)=10//可以的,引用的内容可变

val修饰的变量还可以用lazy修饰,值是在需要使用的时候才会赋值

 

官方推荐使用val

 

  1. 数据类型和操作符

数据类型

  1. 值类型(java中的基本数据类型)和引用类型
  2. 值类型也是类类型,相当于java中的包装类,没有基本数据类型和包装类之分

scala基础语法_第7张图片

操作符

数学运算符

关系运算符

逻辑运算符

位运算符

比较对象 == !=

  1. Scala中的运算符都是方法的重载,是方法的调用

scala基础语法_第8张图片

  1. scala中没有++, --,可用+=,-=来代替
  1. 表达式

就是一个语句块,包含一条或者多条语句

特点:

  1. 表达式是有返回值的
  2. 返回值是表达式中最后一条语句的执行结果

条件表达式

含有if/else的表达式

scala基础语法_第9张图片

 

块表达式

一条语句或者多条语句

scala基础语法_第10张图片

  1. 循环

for:

         for(i <- 表达式、数组、集合)

 

while

         while(条件语句){表达式}

 

do while

 

         do{表达式}while{条件语句}

 

scala基础语法_第11张图片

scala基础语法_第12张图片

scala基础语法_第13张图片

scala基础语法_第14张图片

scala基础语法_第15张图片

ab34f96e8c97e4af3c52bba260f99bbcf12.jpg

  1. 方法

定义语法:

def 方法名(参数名1:参数类型,参数名2:参数类型,…):返回类型=方法体

返回类型可省略,如果是递归方法则不可省略。系统会根据表达式的返回值推断方法的返回值的类型。

 

scala基础语法_第16张图片  

scala基础语法_第17张图片

上述报错的原因是,方法的返回值定义的是int类型,而方法体表达式最后一行是print函数,它的返回值是Unit类型(注意表达式的返回值是它最后一行语句的返回值)。因此要将方 法返回值改为Unit或缺省,由系统自己去判断。

 

无参方法

scala基础语法_第18张图片

 

带有默认值参数的方法

scala基础语法_第19张图片  

可变长参数方法

scala基础语法_第20张图片

 

  1. 函数

定义函数时格式:val 变量名 = (输入参数类型和个数) => 函数实现和返回值类型和个数

“=”表示将函数赋给一个变量

“=>”左面表示输入参数名称、类型和个数,右边表示函数的实现和返回值类型和参数个数

定义函数

06190ebe35f4f292ed84a526161966fedfa.jpg

 

scala基础语法_第21张图片  

无参函数

8c67599faa723954136ccc44968db2a1d24.jpg

匿名函数定义, 左边是参数 右边是函数实现体 x: Int=>{} 
函数类型的声明,左边是参数类型,右边是方法返回值类型 (Int)=>(Int) 

函数作为参数的表现形式——函数名:传入参数*=>返回值
     def getName(func:String=>Unit,name:String){   //getName两个参数,第一个是函数参//数,第二个是name
       func(name)
}
 
 
   

 

f(p :=>Int)

scala基础语法_第22张图片

注意:def a(f: =>Int)={}冒号后面要有个空格

在Scala中,你不需要给每一个函数命名,没有将函数赋给变量的函数叫做匿名函数

scala基础语法_第23张图片

由于Scala可以自动推断出参数的类型,所有可以写的跟精简一些

94d9bd6312d862c1d3659646f79a9fcc5d3.jpg

还记得神奇的下划线吗?这才是终极方式

9d9c9b37869684d90a855033fd9bf0c4b0d.jpg

//第一种:最直观的方式 (Int) => Int

    //new_list = list.map((x: Int) => x * 3)

    //第二种:由于map方法知道你会传入一个类型为(Int) => Int的函数,你可以简写

    //new_list = list.map((x) => x * 3)

    //第三种:对于只有一个参数的函数,你可以省去参数外围的()

    //new_list = list.map(x => x * 3)

//第四种:(终极方式)如果参数在=>右侧只出现一次,可以使用_

  new_list = list.map(_ * 3)

  1. 集合

集合是存储各种数据类型对象的一个容器

  1. 是一个容器
  2. 一般放同种数据类型的对象
  3. 一般存放多个对象

集合分为不可变集合和可变集合。

不可变集合:不可修改,但是可以模拟修改或者删除等操作。返回一个新的集合,原来集合不变。

可变集合:可修改,更新,扩充。

 

三大类

Set 序列 map

 scala基础语法_第24张图片

  1. 定长数组

scala基础语法_第25张图片

  1. 变长数组

scala基础语法_第26张图片

scala基础语法_第27张图片  

 

scala基础语法_第28张图片scala基础语法_第29张图片

 

数组变换

scala基础语法_第30张图片

 

  1. List

scala基础语法_第31张图片

 

  1. Map

scala基础语法_第32张图片

 

 

scala基础语法_第33张图片

 

  1. 元组

scala基础语法_第34张图片

scala基础语法_第35张图片

scala基础语法_第36张图片

  1. Set

特点

set中的元素是不许重复的

set中元素是无序随机的

 

scala基础语法_第37张图片

scala基础语法_第38张图片

  1. 集合中重要函数
  1. sum max min

scala基础语法_第39张图片

  1. filter

8a36c22a6e204702f039a701775216b3a8f.jpg

  1. flatten 是对集合中包含的集合的集合做处理

scala基础语法_第40张图片

 

  1. map

scala基础语法_第41张图片

  1. flatMap 有点类似于map+flatten

scala基础语法_第42张图片

 

  1. forall foreach

scala基础语法_第43张图片

  1. foldLeft foldRight reduceLeft reduceRight

reduceLeft:从左边往右边计算 reduceRight相反 reduce相当于redeceLeft

scala基础语法_第44张图片

scala基础语法_第45张图片

scala基础语法_第46张图片

  1.  java中面向对象的概念

类:类是一类事物的抽象

对象:类的一个实例

 

 

 

scala基础语法_第47张图片

 

foldLeft foldRight 相对于reduceLeft 和reduceRight要多一个多传入一个参数

scala基础语法_第48张图片

scala基础语法_第49张图片

  1. 类和属性定义

scala基础语法_第50张图片

this.age-obj.age会出错,因为private[this]修饰的自由当前对象可以访问。

 

 

  1. 构造函数

19.1默认的主构造函数是无参构造函数

(1)类自带无参构造函数函数

(2)主构造函数执行类中定义的所有语句

class ConstructorDemo{
 
var a:Int=0
 
println("constructor")

}

object ConstructorDemo{
 
def main(args: Array[String]): Unit = {
   
val obj=new ConstructorDemo()

    println(obj.
a)
  }

}

 

19.2自定义辅助构造函数

class ConstructorDemo{

 var a:Int=0

 println("constructor")



  def this(a1:Int){

    this()//首先要调用主构造函数或者其他的辅助构造函数

    this.a=a1

  }





}

object ConstructorDemo{

  def main(args: Array[String]): Unit = {

    //val obj=new ConstructorDemo()

  val obj=new ConstructorDemo(1000)

    println(obj.a)

  }



}

 

19.3自定义带参数的主构造函数

class ConstructorDemo(var b:Int){

  println(b)



}

object ConstructorDemo{

  def main(args: Array[String]): Unit = {

  val obj=new ConstructorDemo(100)

    println(obj.b)

  }



}

注意当构造函数中的参数用var修饰时,会被当做是类中的属性,如果没有var修饰时,则不会

class ConstructorDemo(b:Int){

  println(b)



}

object ConstructorDemo{

  def main(args: Array[String]): Unit = {

  val obj=new ConstructorDemo(100)

    println(obj.b)

  }



}

 

Error:(8, 17) value b is not a member of ConstructorDemo

    println(obj.b)

 

19.4在自定义的带参数的主构造函数中定义辅助构造函数

class ConstructorDemo(b:Int){

  println(b)

  def this(a1:Int,b1:Int){

    this(a1)  //调用主构造函数

  }

}

object ConstructorDemo{

  def main(args: Array[String]): Unit = {

  val obj=new ConstructorDemo(100)



  }



}

19.5定义私有的主构造函数

class ConstructorDemo private(b:Int){

  println(b)

  def this(a1:Int,b1:Int){

    this(a1)

  }

}

object ConstructorDemo{

  def main(args: Array[String]): Unit = {

  val obj=new ConstructorDemo(100)



  }



}
  1. 单例对象和伴生对象

单例对象,以object关键字修饰的就是单例对象

//单例对象,scala中没有静态方法和静态字段,这个作用类似

//相当于java中的一个工具类,可以定义工具函数和常量

//单例对象第一次调用时初始化

object Logger {

  def log(msg:String): Unit ={

    println(s"Info:$msg")

  }

}



class Test{

  def method={

   Logger.log("hahah")

  }

}



object LoggerTest{

  def main(args: Array[String]): Unit = {

    Logger.log("haha")

    val obj=new Test

    obj.method

  }

}

 

类的伴生对象,伴生对象和类可以互相访问彼此的私有属性或者方法。类和对象定义在同一个源文件中且名字相同,则是伴生类和伴生对象。

class AccountInfo {

    var id=AccountInfo.newUniqueNumber



}

object AccountInfo{



  private var lastNumber:Int=10

  private def newUniqueNumber={

    lastNumber+=1

    lastNumber

  }

}

object test{

  def main(args: Array[String]): Unit = {

    val obj=new AccountInfo

    println(obj.id)

  }

}

 

程序的执行可以在单例对象中定义main方法,也可以在应用程序对象中定义要执行的语句

import javafx.application.Application

class AccountInfo {

    var id=AccountInfo.newUniqueNumber



}

object AccountInfo{



  private var lastNumber:Int=10

  private def newUniqueNumber={

    lastNumber+=1

    lastNumber

  }

}



/*

object test{

  def main(args: Array[String]): Unit = {

    val obj=new AccountInfo

    println(obj.id)



  }

}*/

object Test extends App{

  val obj=new AccountInfo

  println(obj.id)

}

此时省略main方法时要导入import javafx.application.Application

  1. apply方法和unapply方法

注意当出现这个问题

b301d2cd9c98b0c137d0ec38cda52cc05c5.jpg

解决:打开run->edit configurations

b301d2cd9c98b0c137d0ec38cda52cc05c5.jpg

将working directory重新选一下

 

class User(val name:String,val password:String) {



}

object User{

  def apply(name:String,password:String)=new User(name,password)



}



object userTest{

  def main(args: Array[String]): Unit = {

    val obj=new User("zhangsan","12345")

    println(obj.isInstanceOf[User])

    val obj1=User("zhangsan","123456")//apply方法可以创建一个类的                        
//对象

    println("result="+obj1.isInstanceOf[User])

  }



}

 

true

result=true

 

class User(val name:String,val password:String) {



}

object User{

  def apply(name:String,password:String)=new User(name,password)



  def unapply(user: User): Option[(String, String)] = {  //unapply方法可以根据传入的对象将对象的属  
                                                                                    //性提取出来

    if(user==null) None

    else

      Some(user.name,user.password)

  }

}



object userTest{

  def main(args: Array[String]): Unit = {

    val obj=new User("zhangsan","12345")

    println(obj.isInstanceOf[User])

    val obj1=User("zhangsan","123456")

    println("result="+obj1.isInstanceOf[User])



    obj match{

      case User(name ,password)=>println(name+":"+password)

      case _ =>println("None")

    }

  }

}

 

  1. 继承

通过extends关键字定义,继承父类的所有属性和方法。

重写父类的非抽象方法,要用override

重写父类的抽象方法,override可选。

final修饰的类,方法,属性不可以被重写

class Point(val xc:Int,val yc:Int) {

  var x:Int=xc

  var y:Int=yc



  def move(dx:Int,dy:Int)={

    x=x+dx

    y=y+dx

    println("x="+x+",y="+y)



  }

}



class Location(override val xc:Int,override val yc:Int,val zc:Int) extends Point(xc,yc){



  var z:Int=zc

  def move(dx:Int,dy:Int,dz:Int)={

    x=x+dx

    y=y+dx

    z=z+dz

    println("x="+x+",y="+y+",z="+z)

  }

}

object test{



  def main(args: Array[String]): Unit = {

    val obj=new Location(5,6,7)

    obj.move(1,2,3)

  }

}

 

注意:

1.判断对象是否属于给定的类

obj.isInstanceOf[Location]

2.类的类型转换

obj.asInstanceOf[Location]

3.获取类的信息

classOf[Location]
  1. 抽象类

抽象类不能被实例化,抽象类可以抽象字段。

抽象字段:没有初始值的字段

抽象方法:没有方法体的方法

abstract class Persons {

  var name:String

  def id:Int

}

抽象类可以有具体的方法,这个方法如果在子类中重写,一定要用override.如若是抽象方法,override可用可不用

  1. trait

优先推荐trait

//定义一个带有抽象方法的特质



trait Iterrator[A] {

  def hasNext:Boolean

  def next():A

}

//定义一个带有实现的方法trait



trait ConsoleLog{

  def log(msg:String)={

    println(msg)

  }



}

//定义一个类实现trait

class IntIterator(to:Int) extends  Iterrator[Int] with ConsoleLog {

  private var current=0

  override def hasNext: Boolean =currentoverride def next(): Int ={

    if(hasNext){

      log("has next")

      val t=current

      current+=1

      t

    }

    else 0

  }

}

object TraitTest {

  def main(args: Array[String]): Unit = {

    val iterator=new IntIterator(10)

    println(iterator.next())

    println(iterator.next())

    println(iterator.next())

  }

}

 

//trait可以为类提供可以堆叠的改变

trait Logger{

  def log(msg:String)



}

//子trait实现父trait里抽象方法

trait ConsoleLogger extends Logger{

  override def log(msg: String): Unit = println(msg)

}

//给日志加上时间戳



trait TimestampLogger extends  ConsoleLogger{

  override def log(msg: String): Unit = super.log(s"${java.time.Instant.now()}$msg")



}

//如果日志时间过长,对日志进行截断显示

trait ShortterLoger extends ConsoleLogger{

  val maxLength=15



  override def log(msg: String): Unit = super.log(

    if(msg.length<=maxLength) msg

    else s"${msg.substring(0,maxLength-3)}..."

  )

}

class Account{

  protected var balance:Double=0.0



}

class SavingAccount extends Account with ConsoleLogger {

  def withdraw(amout: Double) = {

    if (amout > balance) log("insufficent funds")

    else balance -= amout

  }

}

object TraintTest2 {

  def main(args: Array[String]): Unit = {

    /*var acc1=new SavingAccount with ConsoleLogger with TimestampLogger with ShortterLoger

    var acc2=new SavingAccount with ConsoleLogger  with ShortterLoger with TimestampLogger

    acc1.withdraw(100.0)

    acc2.withdraw(100.0)*/

  }

}
  1. 样例类
object CaseClassDemo {

  def main(args: Array[String]): Unit = {

    //定义样例类

    //默认带有apply方法

    //构造函数的默认参数默认是public val修饰的,值不可以修改但是可以改为var,这样值就可以修改,但是不推荐

    case class Message(send:String,recipient:String,body:String)

    //创建样例类对象



    val message1=Message("Jery","Tom","I Love you")

    println(message1)



    //样例类的比较,基于值或者结构的比较,而不是基于引用的比较

    val message2=Message("Jery","Tom","I Love you")

    if(message1==message2)

      println("same")

    else println("different")



    //样例类的拷贝,浅拷贝

    val message3=message1.copy()

    println(message3)

    //不完全拷贝,对部分参数赋值

    val message4=message1.copy(send = "lingxiao")

    println(message4)

  }

}
  1. 模式匹配

Java switch

常量模式匹配

变量模式匹配

通配符模式匹配

样例类匹配

类型匹配

object PatternDemo {

  def main(args: Array[String]): Unit = {

    //常量模式匹配

    //1.常量字面值匹配

    val site="qianfeng.com"

    site match{

      case "qianfeng.com" => println("1.success")

      case _=>println("1.fail") //相当于java中的default,不需要break语句



    }

    //2.常量变量匹配

    val QIANFENG="qianfeng.net" //常量变量的匹配,变量名一定要大写

    //val qianfeng="qianfeng.net"

    site match{

     // case qianfeng => println("2.success")

      case QIANFENG => println("2.success")

      case _=>println("2.fail") //相当于java中的default,不需要break语句



    }

    //3.变量模式匹配

    val qianfeng="qianfeng.net"

    site match{

       case qianfeng => println(qianfeng+" 3.success") //变量模式匹配,site 会把值赋给qianfeng

      case _=>println("3.fail") //相当于java中的default,不需要break语句

    }

    //4.通配符模式匹配,通配符用_表示,可以理解为占位符

    val list =List(1,2,3)

    list match{

      case List(_,_,3)=>println("4.success") // 判断List是否符合第三个元素是3,前两位不管

      case _ => println("4.fail")

    }

  }

}
 
 
 
//样例类匹配
abstract class Notification

//定义不同信息的样例类

case class Email(sender:String,title:String,body:String) extends Notification

case class SMS(caller:String,message:String) extends Notification

case class VoiceRecording(contactName:String,link:String) extends Notification



object PatternDemo2 {

  //做信息的识别

  def main(args: Array[String]): Unit = {

    //样例类匹配,做信息的甄别

    def showNotification(notification: Notification)={

      notification match {

        case Email(sender,title,body) if(sender=="lingxiao")=> "you get a Email Message from "+sender+" context: "+body

        case SMS(caller,message) => "you get a SMS message from " + caller

        case VoiceRecording(contactName,link) => "you get a voiceRecording message from "+contactName

        case _ =>""

      }

    }

    //创建一条信息

    val email=Email("lingxiao","important","I love you")

    println(showNotification(email))

    }

}


//类型匹配

val arr=Array("string",1,2.0,'c')

//随机取数组的元素

val obj=arr(Random.nextInt(4))

println(obj)



obj match {

  case x:Int => println(x)

  case x:String => println(x.toUpperCase())

  case x:Double => println(x)

  case _ => println("failed")

}

 

 

 

 

 

Option类型的模式匹配

scala基础语法_第51张图片

  1. 偏函数

1.使用标准的方法定义偏函数

object PartialFunctionDemo {

  //创建一个普通函数



  val div1=(x:Int)=> 100/x



  //定义一个偏函数

  val div2=new PartialFunction[Int,Int] {

    override def isDefinedAt(x: Int): Boolean = x!=0



    override def apply(x:Int): Int = 100 / x

  }



  def main(args: Array[String]): Unit = {

   // div1(0) //会出错

    println(div2.isDefinedAt(1))

    if(div2.isDefinedAt(0))

      div2.apply(0)

    else println("不允许运算")

    

    if(div2.isDefinedAt(1))

      println(div2.apply(1))

    else println("不允许运算")

    println(div2.isDefinedAt(0))

  }

 

2.简洁方式定义偏函数

偏函数本质上是由多个case语句组成的针对每一种可能的参数分别进行处理的一种“结构较为特殊”的函数,那特殊在什么地方呢?对,就是case语句,前面我们提到,case语句声明的变量就是偏函数的参数,既然case语句只能声明一个变量,那么偏函数受限于此,也只能有一个参数!说到底,类型PartialFunction无非是为由一组case语句描述的函数字面量提供一个类型描述而已,case语句只接受一个参数,则偏函数的类型声明自然就只有一个参数。

object PartialFunctionDemo {

  val div3:PartialFunction[Int,Int]={ 
//第一个参数是要处理的类型,第二个参数是返回的类型

    case d:Int if(d!=0) => 100/d

    case _ => 0

  }

  def main(args: Array[String]): Unit = {

    println(div3(0))

 }}
 
object PartialFunctionDemo {



  val div3:PartialFunction[Int,String]={

    case d:Int if(d!=0) => (100/d).toString

    case _ => "by zero"

  }

  def main(args: Array[String]): Unit = {

    println(div3(1))



  }

}
 
object PartialFunctionDemo {



  val res:PartialFunction[Int,String]={

    case 1 => "one"

    case 2 => "two"

    case _ =>"other"



  }

  def main(args: Array[String]): Unit = {



    println(res.isDefinedAt(1))

      println(res(10))

  }

}
object PartialFunctionDemo {



  val res:PartialFunction[Int,String]={

    case 1 => "one"

    case 2 => "two"

    case _ =>"other"



  }

  //orElse 组合多个偏函数成为一个整体

  val r1:PartialFunction[Int,String]={case 1=>"one"}

  val r2:PartialFunction[Int,String]={case 2=>"two"}

  val r3:PartialFunction[Int,String]={case _=>"other"}



  val res2 = r1 orElse r2 orElse r3 //相当于res这个函数



  //andThen,将多个偏函数串行执行



  val r4:PartialFunction[Int,String]={case cs if(cs==1) =>"one"}

  val r5:PartialFunction[String,String]={case cs if(cs.eq("one")) =>"1"}

  val r6:PartialFunction[String,Double]={case cs if(cs.eq("1"))=>1}

  val res3:(Int=>Double)= r4 andThen r5 andThen r6 
//Int=>Double 最开始传入的是Int类型,最后返回的是Double类型





  def main(args: Array[String]): Unit = {



   /* println(res.isDefinedAt(1))

    println(res(10))

    println(res2(1))

    */

    println(res3(1))

  }

}

 

  1. 密封类

用关键字sealed修饰的类或者特质

约束:不能再类定义文件之外定义它的子类

作用:

  1. 可以避免滥用继承
  2. 用在模式匹配中,检查所有的匹配情况是否匹配完全。而不用使用通配符的情况。
sealed abstract  class Furniture

case class Couch() extends Furniture

case class Chair() extends Furniture

object SealedDemo {

  def findPlaceToSit(furniture: Furniture)=furniture match {

    case a:Couch => "lie on the couch"

    case a:Chair => "sit on the chari"

    //case _=>""不需要这个,因为Furniture是sealed密封类

  }

  val chair =Chair()



  def main(args: Array[String]): Unit = {

    println(findPlaceToSit(chair))

 }

}

 

 

  1. Option

如何定义Option类型

scala基础语法_第52张图片

scala基础语法_第53张图片

map.getOrElse(“c”,”默认值”),如果map中键c不存在,则返回默认值。也可以使用Option类型,它有两个类,一个用例类Some,一个None

 

object OptionDemo {



  def main(args: Array[String]): Unit = {

    val map=Map("a"->1,"b"->2)

    println(map("b"))



    //println(map("c"))

   println( map.getOrElse("c","morenzhi"))



    val a:Option[Int]=map.get("a")

    println(a.getOrElse())

    val b:Option[Int]=map.get("c")

    println(b.getOrElse())

  }

}
  1. 字符串插值器
object StringDemo {

  def main(args: Array[String]): Unit = {

    //插值器 f s raw

    //s字符串插值器

    val name = "lingxiao"

    val res =s"Hello,$name"

    //  对${ }中的表达式进行运算

    val res1= s"1+1=${1+1}"

    println(res)

    println(res1)

    //f插值器,对字符串进行格式化

    val height=1.9d

    val heigt1=1

    val res2=f"$heigt1%2.5f is $height%2.2f meters tall" //%2.2f必须紧跟着$height

    println(res2)

    //raw插值器,类似于s插值器,不对其中的内容做转换

    val str=s"a\nb"

    println(str)

    val str2=raw"a\nb"

    println(str2)

  }}

scala基础语法_第54张图片

  1. 文件操作
//读取文件一行

/* //读取文件一行

    val source = Source.fromFile("src/filetest.txt")

    //获取文件行迭代器

    val lines=source.getLines()

    for(line<-lines)

      println(line)

    //关闭源文件

    source.close();*/



/*    //按每一个字符读取文件

    val source1=Source.fromFile("src/filetest.txt")

    val iter=source1.buffered

    while(iter.hasNext){

      println(iter.next())

    }

    source1.close()

    */

/*    //读取网络文件

    val source2=Source.fromURL("https://baike.baidu.com/item/Scala")

    val lines=source2.getLines()

    for(line<-lines)

      println(line)

    source2.close()*/



    //写文件

    val out = new PrintWriter("file1.txt")

    for(i<-1 to 100)

      out.println(i)

  out.close()
 
  1. 正则表达式

主要用来对字符串进行检索匹配

import scala.util.matching.Regex

object RegDemo {

  def main(args: Array[String]): Unit = {

      //构造一个正则表达式

    val pattern1="[0-9]+".r

    val pattern2=new Regex("[0-9]+")



    //如果正则表达式有\,"", 可以用""" """

    val pattern3=""" \s+[0-9]+\s"""



    val matchStr="99bottles,100bottles"

    //findAllIn返回所有匹配项的迭代器

   for(item<- pattern1.findAllIn(matchStr))

     println(item)



    //返回首个匹配项

    println(pattern1.findFirstIn(matchStr))



    //检查字符串的开始部分是不是能匹配

    println(pattern1.findPrefixOf(matchStr))



    //使用传入的字符串替换首个匹配项

    println(pattern1.replaceFirstIn(matchStr,"xxx"))



    //使用传入的字符串替换所有匹配项

    println(pattern1.replaceAllIn(matchStr,"xxx"))

  }

}

 

 

 

 

 

 

 

 

 

  1. 高阶函数

高阶函数:一个函数的参数是函数,或者它的返回值是函数。

object HFunDemo {

  def main(args: Array[String]): Unit = {

  //传入参数是函数

    val arr=Array(1,2,3,4,5)

    val fun=(x:Int)=>x*2

    val res=arr.map(fun) //map是高阶函数

    println(res.toBuffer)

    //传入匿名函数

    val res1=arr.map((x:Int)=>x*2) //val res1=arr.map(_*2)



    //返回值是函数

    def urlBuilder(ss1:Boolean,domainName:String):(String,String)=>String={

        val schema =if(ss1) "https://" else "http://"

      (endpoint:String,query:String)=>s"$schema$domainName/$endpoint?$query"

    }

    val domainName="www.baidu.com"

    def getUrl:(String,String)=>String =urlBuilder(ss1=true,domainName)

    //val getUrl:(String,String)=>String =urlBuilder(ss1=true,domainName) //定义一个变量getUrl,变量的类型是函数来接受 urlBuilder的返回值

    val endpoint ="users"

    val query="id=1"

    val res3=getUrl(endpoint,query)

    println(res3)}}
 
  1. 闭包

闭包是一个函数,函数的返回值依赖于函数外部的一个或者多个变量

var factor=10   //变量factor和multiply3函数形成了一个闭包

val multiply3=(x:Int)=>{  

  factor+=10

  x*factor

}

 

 

 

  1. 柯里化

柯里化是把接收多个参数的函数变成接收一个单一参数的函数,返回一个接收余下参数的新函数

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  1. 方法的嵌套和多态
object MethodDemo extends App {



  //方法的嵌套:方法体里面定义其他嵌套

  //阶乘

  def fatorial(x:Int):Int={

    def fact(x:Int,accumulator:Int):Int={

      if(x<=1) accumulator

      else fact(x-1,x*accumulator)

    }

    fact(x,1)

  }

  println(fatorial(5))



  //方法的多态:方法可以通过类型实现参数化,类似泛型

  def listOfDuplicates[A](x:A,length:Int):List[A]={

    if(length<1) Nil

    else

      x::listOfDuplicates(x,length-1)



  }

  println(listOfDuplicates(3,5))

  println(listOfDuplicates("ss",10))





}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  1. 隐式转换

 



  //定义隐式类,可以把File类转成自定义的隐式类RichFile

  //使用隐式类做已有类的动能的扩展

  implicit class RichFile(from:File){

    def read=Source.fromFile(from.getPath).mkString

  }

 val contents= new File("src/file1.txt").read

  println(contents)

}

object ImplictClassDemo extends App {

  //定义一个隐式类

  //隐式类智能定义在类,trait,object内部

  implicit  class IntWithTimes(x:Int){

    def times[A](f: =>A)={

      def loop(current:Int):Unit={  //递归方法需要指明其返回类型

        if(current>0){

          f

          loop(current-1)

        }

      }

      loop(x)

    }

  }

//隐式类的构造函数只能带一个非隐式参数

  //implicit  class Indexer[T](collection:Seq[T],index:Int)

implicit  class Indexer[T](collection:Seq[T])(implicit  index:Int)



  //在同一作用域,不能有方法或者对象,成员和隐式类同名



}

 

scala基础语法_第55张图片

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  1. 闭包

 

 

 

 

转载于:https://my.oschina.net/u/4027246/blog/2876842

你可能感兴趣的:(scala基础语法)