scala方法函数学习小结

yield

yield会把当前元素给记录下来,并保存到集合中

 val v = for(i <- 1 to 10) yield i * 10
    println(v)

结果:

Vector(10, 20, 30, 40, 50, 60, 70, 80, 90, 100)

var val

var修饰的变量是可变的,val是不可变的

break

package com.xu

import scala.util.control.Breaks._
object ScalaTest {

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

    breakable {
      for(i <- 1 to 10) {
        if(i >= 5)
          break()
        else
          println(i)
      }

    }

  }

}

continue

package com.xu
import scala.util.control.Breaks._
object ScalaTest {
  def main(args: Array[String]): Unit = {
      for(i <- 1 to 100) {
        breakable {
          if(i % 10 == 0)
            break()
          else
            println(i)
        }
    }
  }
}

定义函数

val 函数变量名 = (参数名:参数类型, 参数名:参数类型…) => 函数体

val add = (x:Int, y:Int) => x + y

def main(args: Array[String]): Unit = {
println(add(1,2))
}

方法无法赋值给一个变量,但是 函数可以赋值给一个变量,那么先将方法转为一个函数:

val add = (x:Int, y:Int) => x + y

  def main(args: Array[String]): Unit = {
    val a = add _
  }

ArrayBuffer

定义变长数据,可加/减/追加
使用+=添加元素
使用-=删除元素
使用++=追加一个数组到变长数组

package com.xu
import scala.collection.mutable.ArrayBuffer
object ScalaTest {
  def main(args: Array[String]): Unit = {
    val a = ArrayBuffer("hadoop", "storm", "spark")
    a += "fluem"
    println(a)
  }
}

数组遍历

val a = Array(5 to 10)
    for(i <- 0 to a.length - 1)
      println(a(i))

元组

元组可以用来包含一组不同类型的值。例如:姓名,年龄,性别,出生年月。元组的元素是不可变的

val a = (1, "zhangsan", 20, "beijing")
println(a._1)
println(a._2)

列表

列表是scala中最重要的、也是最常用的数据结构。List具备以下性质:

可以保存重复的值
有先后顺序

使用::拼接方式来创建列表,必须在最后添加一个Nil

不可变列表创建:

val a = List(1,2,3,4)
val a = -2 :: -1 :: Nil

可变列表创建及操作:

package com.xu
import scala.collection.mutable.ListBuffer
object ScalaTest {
  def main(args: Array[String]): Unit = {
    val a = ListBuffer[Int]()
    val b = ListBuffer(1,2,3,4)

    println(a += 4) //追加一个元素
    println(a ++= List(9,8,7)) //追加一个列表
    println(a -= 4) // 删除元素
    println(a.toList) // 转换为不可变列表
    println(a.toArray) // 转换为数组
  }
}

列表常用操作

val a = List(1,2,3,4,5)
println(a.head) //获取头
println(a.tail) //获取除第一个元素以外的元素,它也是一个列表
println(a.reverse) //反转列表
println(a.take(3)) //获取前三个元素
println(a.drop(3)) //除去前三个的元素

val b = List(List(1,2), List(3), List(4,5))
println(b.flatten) //扁平化

Set 与 Map

导入对应的包,就是可变的

import scala.collection.mutable.Set
import scala.collection.mutable.Map

override和super

package com.xu
object ScalaTest {

  class Person {
    val name = "super"
    def getName = name
  }
  class Student extends Person {
    // 重写val字段 子类要覆盖父类中的一个方法,必须要使用override关键字
    override val name: String = "child"
    // 重写getName方法
    override def getName: String = "hello, " + super.getName
  }
  def main(args: Array[String]): Unit = {
    println(new Student().getName)
  }
}

isInstanceOf/asInstanceOf

isInstanceOf判断对象是否为指定类的对象
asInstanceOf将对象转换为指定类型

package com.xu
object ScalaTest {
  class Person3
  class Student3 extends Person3
  def main(args: Array[String]): Unit = {
    val s1:Person3 = new Student3
    if(s1.isInstanceOf[Student3]) {
      var s2 = s1.asInstanceOf[Student3]
      println(s2)
    }
  }
}

getClass和classOf

isInstanceOf 只能判断对象是否为指定类以及其子类的对象,而不能精确的判断出,对象就是指定类的对象。如果要求精确地判断出对象就是指定类的对象,那么就只能使用 getClass 和 classOf

package com.xu
object ScalaTest {
  class Person3
  class Student3 extends Person3
  def main(args: Array[String]): Unit = {
    val p:Person3 = new Student3
    println(p.getClass == classOf[Person3])
    println(p.getClass == classOf[Student3])
  }
}

匿名内部类

package com.xu
object ScalaTest {
  abstract class Person {
    def sayHell:Unit
  }
  def main(args: Array[String]): Unit = {
    val p1 = new Person {
      override def sayHell: Unit = println("我是一个内部类")
    }
    p1.sayHell
  }
}


trait作为接口使用

使用extends来继承trait(scala不论是类还是特质,都是使用extends关键字)

如果要继承多个trait,则使用with关键字

package com.xu
object ScalaTest {
  trait Logger {
    def log(message:String)
  }
  class ColsoleLogger extends Logger {
    override def log(message: String): Unit = println("控制台打印:" + message)
  }
  def main(args: Array[String]): Unit = {
    val logger = new ColsoleLogger
    logger.log("hahha")
  }
}

特质 | 定义具体的方法

package com.xu
object ScalaTest {
  trait LoggerDate {
    def log(msg:String) = println("打印:" + msg)
  }
  class UserService extends LoggerDate {
    def add() = log("添加用户")
  }
  def main(args: Array[String]): Unit = {
    val userService = new UserService
    userService.add()
  }
}

使用trait实现模板模式

要实现以下需求:

实现一个输出日志的功能
目前要求输出到控制台
将来可能会输出到文件、输出到Redis、或者更多的需求

package com.xu
object ScalaTest {
  trait Logger {
    def log(msg:String)
    def info(msg:String) = log("info级别:"+msg)
    def warn(msg:String) = log("warn级别:" + msg)
  }
  class ConsoleLogger extends Logger {
    override def log(msg: String): Unit = {
      println(msg)
    }
  }
  def main(args: Array[String]): Unit = {
    val logger = new ConsoleLogger
    logger.info("信息日志")
    logger.warn("警告日志")
  }
}

trait实现调用链模式

类继承了多个trait后,可以依次调用多个trait中的同一个方法,只要让多个trait中的同一个方法在最后都依次执行super关键字即可。类中调用多个tait中都有这个方法时,首先会从最右边的trait方法开始执行,然后依次往左执行,形成一个调用链条。

步骤

定义一个HandlerTrait特质
定义一个具体的handler方法,打印"处理数据…"

定义一个DataValidHandlerTrait,继承HandlerTrait特质
重写handler方法,打印"验证数据"
调用父特质的handler方法

定义一个SignatureValidHandlerTrait,继承HandlerTrait特质
重写Handler方法
打印"检查签名"
调用父特质的handler方法

创建一个PaymentService类
继承DataValidHandlerTrait
继承SignatureValidHandlerTrait
定义pay方法
打印"准备支付"
调用父特质的handler方法

添加main方法
创建PaymentService对象实例
调用pay方法

package com.xu
object ScalaTest {
  trait HandlerTrait {
    def handle(data:String) = println("5.处理数据....")
  }

  trait DataValidHanlder extends HandlerTrait {
    override def handle(data: String): Unit = {
      println("4.验证数据....")
      super.handle(data)
    }
  }

  trait SignTureValidHandler extends HandlerTrait {
    override def handle(data: String): Unit = {
      println("3.校验签名....")
      super.handle(data)
    }
  }

  //这里的继承顺序,执行父级的及执行顺序,现有写法,先执行sign中的
  class PayService extends DataValidHanlder with SignTureValidHandler {
    override def handle(data: String): Unit = {
      println("2.准备支付....")
      super.handle(data)
    }
  }

  def main(args: Array[String]): Unit = {
    val service = new PayService
    service.handle("开始啦!!")
  }
}

样例类

样例类是一种特殊类,它可以用来快速定义一个用于保存数据的类(类似于Java POJO类),在后续要学习并发编程和spark、flink这些框架也都会经常使用它。

package com.xu
object ScalaTest {
    case class Person(name:String, age:Int)
    def main(args: Array[String]): Unit = {
      val zhangsan = Person("张三", 20)
      println(zhangsan)
    }
}

变量声明中的模式匹配

获取数组中的元素

val array = (1 to 10).toArray
val Array(_, x, y, z, _*) = array

println(x, y, z)

获取List中的数据

val list = (1 to 10).toList
val x :: y :: tail = list

println(x, y)

Option类型

使用Option类型,可以用来有效避免空引用(null)异常。也就是说,将来我们返回某些数据时,可以返回一个Option类型来替代。

package com.xu

import scala.io.StdIn

object ScalaTest {
    def div(a:Double, b:Double) : Option[Double] = {
        if(b != 0) {
            Some(a / b)
        } else {
            None
        }
    }
  def main(args: Array[String]): Unit = {
    val reslut = div(1.0, 2.0)
    reslut match {
      case Some(x) => println("不是None")
      case None => println("这个是none啊")
    }
  }
}

使用getOrElse方法,当除零时,或者默认值为0

def dvi(a:Double, b:Double) = {
    if(b != 0) {
        Some(a / b)
    }
    else {
        None
    }
}

def main(args: Array[String]): Unit = {
    val result = dvi(1, 0).getOrElse(0)

    println(result)
}

偏函数

偏函数被包在花括号内没有match的一组case语句是一个偏函数

偏函数是PartialFunction[A, B]的一个实例

A代表输入参数类型
B代表返回结果类型

// func1是一个输入参数为Int类型,返回值为String类型的偏函数
val func1: PartialFunction[Int, String] = {
    case 1 => "一"
    case 2 => "二"
    case 3 => "三"
    case _ => "其他"
}

println(func1(2))

异常处理

try {
    val i = 10 / 0

    println("你好!")
} catch {
    case ex: Exception => println(ex.getMessage)
}

提取器(Extractor)

样例类自动实现了apply、unapply方法

另外伴生对象中,要实现一个类的提取器,只需要在该类的伴生对象中实现一个unapply方法即可

class Student(var name:String, var age:Int)

object Student {
    def apply(name:String, age:Int) = {
        new Student(name, age)
    }

    def unapply(student:Student) = {
        val tuple = (student.name, student.age)

        Some(tuple)
    }
}

def main(args: Array[String]): Unit = {
    val zhangsan = Student("张三", 20)

    zhangsan match {
        case Student(name, age) => println(s"${name} => ${age}")
    }
}

泛型

不同类型集合,求中间值

def getMiddleElement[T](array:Array[T]) =
array(array.length / 2)

def main(args: Array[String]): Unit = {
    println(getMiddleElement(Array(1, 2, 3, 4, 5)))
    println(getMiddleElement(Array("a", "b", "c", "d", "e")))
}

正则表达式

val r = """.+@.+\..+""".r

val eml1 = "qq12344@163.com"
val eml2 = "qq12344@.com"

if(r.findAllMatchIn(eml1).size > 0) {
    println(eml1 + "邮箱合法")
}
else {
    println(eml1 + "邮箱不合法")
}

if(r.findAllMatchIn(eml2).size > 0) {
    println(eml2 + "邮箱合法")
}
else {
    println(eml2 + "邮箱不合法")
}

val emlList =
      List("38123845@qq.com", "a1da88123f@gmail.com", "zhansan@163.com", "123afadff.com")
    val regex = """.+@.+\..+""".r
    val invalidEmlList = emlList.filter {
      //返回结果为ture的 ,即输出合法的邮箱有那些,
      x => if (regex.findAllMatchIn(x).size > 0) true else false
    }
    println(invalidEmlList)

匹配邮件的所属机构:

// 使用括号表示一个分组
    val regex = """.+@(.+)\..+""".r
    val emlList =
      List("38123845@qq1.2.c.n", "a1da88123f@gmail1.2c.com", "zhansan@163.com", "123afadff.com")
    val emlCmpList = emlList.map {
      //匹配是倒数第一位点
      case x@regex(compan) => s"${x} => ${compan}"
      case x => x + "=>未知"
    }

泛型类

case class Pair[T](var a:T, var b:T)

def main(args: Array[String]): Unit = {
    val pairList = List(
        Pair("Hadoop", "Storm"),
        Pair("Hadoop", 2008),
        Pair(1.0, 2.0),
        Pair("Hadoop", Some(1.9))
    )

    println(pairList)
}

上下界

需求:

我们在定义方法/类的泛型时,限定必须从哪个类继承、或者必须是哪个类的父类。此时,就需要使用到上下界。

class Person
class Student extends Person

def demo[T <: Person](a:Array[T]) = println(a)

def main(args: Array[String]): Unit = {
    demo(Array(new Person))
    demo(Array(new Student))
    // 编译出错,必须是Person的子类
    // demo(Array("hadoop"))
}

class Person
class Policeman extends Person
class Superman extends Policeman

def demo[T >: Policeman](array:Array[T]) = println(array)

def main(args: Array[String]): Unit = {
    demo(Array(new Person))
    demo(Array(new Policeman))
    // 编译出错:Superman是Policeman的子类
    // demo(Array(new Superman))
}

协变、逆变、非变

让带有泛型的类支持类型转换

class Super
class Sub extends Super

class Temp1[T] // 非变
class Temp2[+T] // 协变
class Temp3[-T] // 逆变

def main(args: Array[String]): Unit = {
    val a:Temp1[Sub] = new Temp1[Sub]
    // 编译报错
    // 非变
    //val b:Temp1[Super] = a

    // 协变 类型B是A的子类型,Pair[B]可以认为是Pair[A]的子类型
    val c: Temp2[Sub] = new Temp2[Sub]
    val d: Temp2[Super] = c

    // 逆变 类型B是A的子类型,Pair[A]反过来可以认为是Pair[B]的子类型
    val e: Temp3[Super] = new Temp3[Super]
    val f: Temp3[Sub] = e
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值