Scala语言的高级特性

一、Scala的集合
    1、可变集合和不可变集合
//可变集合、不可变集合  Map
val math = scala.collection.immutable.Map("Alice"->80,"Bob"->90)

val chinese = scala.collection.mutable.Map("Alice"->80,"Bob"->90)

//1. 获取集合中的值
chinese("Bob")
if(chinese.contains("Bob")){
  chinese("Bob")
}else{
  -1
}
//简写
chinese.getOrElse("Bob1",-1)

//2、修改更新可变集合中的值
chinese("Bob")=100
//添加新的元素
chinese += "Jerry"-> 79
//删除元素
chinese -= "Bob"

//迭代
for(s <- chinese) println(s)
chinese.foreach(println)

    2、列表:List
import scala.collection.mutable
//可变列表  不可变列表

//不可变列表 : List

//字符串的List
val nameList = List("Mary","Tom","Mike")
//整数列表
val intList = List(1,2,3,4)
//空列表
val nullList:List[Nothing] = List()
//二维列表
val din:List[List[Int]] = List(List(1,2,3),List(4,5,6))

//操作
println("第一个人的名字:"+nameList.head)
println("除去第一个元素后,剩下的元素:"+nameList.tail)

//可变列表(LinkedList):可以修改里面的值
val myList = mutable.LinkedList(1,2,3,4,5,6)

//操作:每个元素乘以2
//类似 PLSQL程序:cursor 游标

//定义一个指针
var cur = myList
//当指针不等于null的时候: Nil:Scala的null值
while(cur != Nil){
  //对当前值乘以2
  cur.elem =cur.elem * 2

  //把指针指向下一个值
  cur = cur.next
}

// 查看结果
println(myList)

    3、序列: 常用的序列: Vector、Range
//序列: 常用的序列: Vector、Range

//Vector: 带下标的序列,从0开始

val v = Vector(1,2,3,4,5,6)

//返回第一个满足条件的元素
v.find( _ > 3)

//更新下标为2的元素值
v.updated(2,100)

//Range: 整数序列
//以下几种写法
println("第一种写法:"+Range(0,5))
println("第二种写法:"+ (0 until 5))
println("第三种写法:"+ (0 to 4))

//两个Range可以相加
('0' to '9') ++ ('A' to 'Z')

//可以把Range 转成一个List
1 to 5 toList

    4、集(Set): 是不重复元素的集合,默认的实现:HashSet
import scala.collection.mutable
//集(Set): 是不重复元素的集合,默认的实现:HashSet

//创建一个Set
var s1 = Set(10,2,0,1)
//往里面添加一个重复的元素
s1 += 0
s1

//往里面添加一个不重复的元素
s1 += 100
s1

//LinkedHashSet
var weeksDay = mutable.LinkedHashSet("星期一","星期二")
weeksDay + "星期五"
weeksDay.contains("星期二")

//可排序的Set
var s2 = mutable.SortedSet(1,2,3,100,10,4)

//判断一个Set是否是另一个Set的子集
Set("星期一","星期二") subsetOf(weeksDay)

//集Set: 并集union、交集intersect、差集 diff
var set1 = Set(1,2,3,4,5,6)
var set2 = Set(5,6,7,8,9,10)

//并集: 去掉重复元素
set1 union set2

//交集
set1 intersect set2

//差集: 从set1中,除去set2
set1 diff set2

    5、模式匹配:相当于Java的 instanceofswitch case
        (*)Scala的一个强大的switch case语句
        (*)类型的检查
//模式匹配

//1、Scala中的switch ... case...
//根据一个变量的值,判断是做加法运算、还是减法运算
var ch1 = '-'
var flag = 0 //flag<0 减法 > 0 加法
ch1 match{
  case '+' => flag = 1
  case '-' => flag = -1
  case _ => flag = 0
}
println(flag)

//2、Scala的守卫:匹配某种类型的所有值
//匹配的所有的数字
var ch2 = '6'
var digit:Int = -1
ch2 match{
  case '+' =>println("这是一个加号")
  case '-' =>println("这是一个减号")
  case _ if Character.isDigit(ch2) => digit = Character.digit(ch2,10)
  case _ => println("其他类型")
}

//3、模式匹配中使用变量
var str3 = "Hello World"
str3(7) match {
  case '+' =>println("这是一个加号")
  case '-' =>println("这是一个减号")
  case ch => println("这个字符是:"+ch)
}

//4、类型的模式
//Any: 任意的类型,类似Java中的Object
var v4:Any = 100
v4 match {
  case x:Int => println("这是一个整数")
  case s:String => println("这是一个字符串")
  case _ => println("其他类型")
}

//5、数组和列表
var myArray = Array(1,2,3)
myArray match{
  case Array(0)  => println("0")
  case Array(x,y) => println("该数组中包含两个元素,和是:" + (x+y))
  case Array(x,y,z) => println("该数组中包含三个元素,和是:" + (x+y+z))
  case Array(x,_*) => println("这是一个数组")
}

var myList = List(1,2,3)
myList match{
  case List(0)  => println("0")
  case List(x,y) => println("该List中包含两个元素,和是:" + (x+y))
  case List(x,y,z) => println("该List中包含三个元素,和是:" + (x+y+z))
  case List(x,_*) => println("这是一个List")
}

    6、样本类: case class
       好处:支持模式匹配
             使用样本类来定义DataFrame(表)的Schema(表的结构) -----> Spark SQL
//使用样本类支持模式匹配: 类似: instanceof

class Vehicle

case class Car(name:String) extends Vehicle
case class Bike(name:String) extends Vehicle

//定义一个Car对象
var aCar:Vehicle = new Car("这是汽车")
aCar match {
  case Car(name) => println("这是一辆汽车")
  case Bike(name)=> println("这是一辆自行车")
  case _ => println("其他类型")
}


二、Scala的泛型: T ----> 重要
    1、泛型类: [T]

//泛型类

//操作Int的类型
//class GenericClass{
//  //定义一个变量
//  private var content:Int = 100
//
//  //定义get和set方法
//  def set(value:Int) = {content = value}
//  def get():Int = {content}
//}

//操作String的类型
//class GenericClass{
//  //定义一个变量
//  private var content:String = "Hello World"
//
//  //定义get和set方法
//  def set(value:String) = {content = value}
//  def get():String = {content}
//}

//问题:能否有一个通用的类,既能操作Int、也能操作String
class GenericClass[T]{
  //定义一个变量
  private var content:T = _

  //定义get和set方法
  def set(value:T) = {content = value}
  def get():T = {content}
}

object GenericClass {

  def main(args: Array[String]): Unit = {
    //操作Int
    var intGeneric = new GenericClass[Int]
    intGeneric.set(123)
    println("得到的值:" + intGeneric.get())

    //操作String
    var stringGeneric = new GenericClass[String]
    stringGeneric.set("Hello Scala")
    println("得到的值:" + stringGeneric.get())
  }
}
    2、泛型函数
        创建一个函数,功能:创建一个Int类型的数组
        def mkIntArray(elems:Int*) = Array[Int](elems:_*)
        mkIntArray(1,2,3,4,5)

        创建一个函数,功能:创建一个String类型的数组
        def mkStringArray(elems:String*) = Array[String](elems:_*)
        mkStringArray("Tom","Mary","Mike")

        问题:能否创建一个通用的函数,既能创建Int类型数组,也能创建String类型的数组
        在泛型函数中:T有要求:必须是ClassTag类型
        import scala.reflect.ClassTag
        def mkArray[T:ClassTag](elems:T*) = Array[T](elems:_*)
        mkArray(1,2,3,4,5)
        mkArray("Tom","Mary","Mike")


        ClassTag: 表示执行Scala程序时的运行信息,该例子中,表示数据的类型

    3、上界和下界:规定泛型的取值范围
        举例:
        (1) 普通数据类型
                 int x 范围
                   100 <= x  <= 200
                   下界         上界

        (2)规定:泛型的取值范围  
                   继承关系
                      A ---> B ---> C ---> D

                      D <:  y泛型 <: B  ====> 表示:y的类型只能是:B  C  D

        概念
           上界:定义 S <: T,表示S的类型必须是T的子类
           下界:定义 U >: T  表示U的类型必须是T的父类
package generic

//上界的例子

//父类: 代表所有的交通工具
class Vehicle{
  //方法
  def drive() = {println("Driving")}
}

//定义两个子类
class Car extends Vehicle{
  override def drive(): Unit = {println("Car Driving")}
}

class Bike extends Vehicle{
  override def drive(): Unit = {println("Bike Driving")}
}

class Apple{

}

object ScalaUpperBound {
  //定义一个泛型函数
  def takeVehicle[T <: Vehicle](v:T) = {v.drive()}

  def main(args: Array[String]): Unit = {
    //定义一个交通工具
    var v1:Vehicle = new Vehicle
    takeVehicle(v1)

    var v2:Car = new Car
    takeVehicle(v2)

    //能否使用Apple?
    var v3:Apple =new Apple
    takeVehicle(v3)
  }
}
    4、视图界定:是上界和下界的一个扩展
        概念:适用范围更广泛 
              以上界为例  <: 
              接收除了所有的子类,还允许接收隐式转换过去的类型
              定义:<%


        看个例子: 定义一个函数完成两个字符串的拼加
        def addTwoString[T <: String](x:T,y:T) = {println(x+"****"+y)}
        调用:addTwoString("Hello","World")

        再调用一次: addTwoString(100,200)  ====> 100*****200
                    100 ---> "100"
                    200 ---> "200"

        使用视图界定重新来定义
           def addTwoString[T <% String](x:T,y:T) = {println(x+"****"+y)}
            表示T的类型:
            (1StringString的子类
            (2)还可以是可以转换成String的类型

            重新调用:addTwoString(100,200)
                    错误:error: No implicit view available from Int => String.

        视图界定的时候:一定有一个转换规则(隐式转换函数)
            implicit def int2String(n:Int):String = {n.toString}

            addTwoString(100,200)
        执行过程: (1) 调用隐式转换函数int2String:  int ====> String
                        100 ---> "100"
                        200 ---> "200"  
                  (2) 再调用addTwoString

    5、协变、逆变
        (*)看成是视图界定的一个扩展
package demo1

//Scala的协变: 一个泛型类接收的泛型参数的值可以是本身的类型或者是子类的类型
//             在泛型前  +

//动物
class Animal{}

//子类:鸟
class Bird extends Animal

//子类:麻雀
class Sparrow extends Bird

//类:吃东西(动作)
class EatSomething[+T](t:T){}

object DemoClass1 {

  def main(args: Array[String]): Unit = {
    //创建一个鸟吃东西的对象
    var c1:EatSomething[Bird] = new EatSomething[Bird](new Bird)

    //创建一个动物吃东西的对象
    //var c2:EatSomething[Animal] = new EatSomething[Animal](new Animal)
    //问题:能否将c1付给c2?
    //原因:尽管Bird是Animal的子类,但是EatSomething[Bird]不是EatSomething[Animal]的子类
    //把EatSomething[Bird]  变成 EatSomething[Animal] 子类
    var c2:EatSomething[Animal] = c1

    //再举个例子
    var c3:EatSomething[Sparrow] = new EatSomething[Sparrow](new Sparrow)
    var c4:EatSomething[Animal] = c3
  }
}
package demo2

//Scala的逆变: 一个泛型类接收的泛型参数的值可以是本身的类型或者是父类的类型
//              语法: -号

//动物
class Animal{}

//子类:鸟
class Bird extends Animal

//子类:麻雀
class Sparrow extends Bird

//定义吃东西的类
class EatSomething[-T](t:T){}


object DemoClass2 {
  def main(args: Array[String]): Unit = {
    //创建一个鸟吃东西的对象
    var c1:EatSomething[Bird] = new EatSomething[Bird](new Bird)

    //创建一个麻雀吃东西的对象
    //var c2:EatSomething[Sparrow] = new EatSomething[Sparrow](new Sparrow)
    //问题:能否将c1 付给c2?
    //原因:尽管Bird是Sparrow的父类,但是EatSomething[Bird]不是EatSomething[Sparrow]的父类
    var c2:EatSomething[Sparrow] = c1
  }
}

    6、隐式转换函数
        (*)前面:implicit def int2String(n:Int):String = {n.toString}

    7、隐式参数

    8、隐式类
package demo3

//水果
class Fruit(name:String){
  def getFruitName():String = {name}
}

//猴子:Monkey
class Monkey(f:Fruit){
  def say() = {println("Monkey like " + f.getFruitName() ) }
}

object ImplicitDemo {

  //定义一个隐式转换函数(规则): Fruit对象 ===> Monkey对象
  implicit def fruit2Monkey(f:Fruit):Monkey = {new Monkey(f)}

  def main(args: Array[String]): Unit = {
    //创建一个水果的对象
    var f:Fruit = new Fruit("香蕉")

    //希望:直接调用 f.say()方法???
    //问题:将Fruit的对象 转换成 Monkey对象?
    f.say()
  }
}

//Scala的隐式参数
def testParam(implicit name:String) = {println("The value is " + name)}

//定义一个隐式参数
implicit val name:String = "这是一个隐式参数"

//调用:不想传递参数
testParam

//作业:P34页
def smaller[T](a:T,b:T)(implicit order:T => Ordered[T]) = if(a < b) a else b
smaller(100,23)
smaller("Hello","ABC")
package demo4

/*
隐式类的功能:对类的功能进行加强
顺序:
第一步:先调用隐式转换类,把  1  ===> Calc对象
第二步:调用Calc对象的add方法
 */
object ImplicitDemo4 {

  //定义一个隐式类
  implicit class Calc(x:Int){
    def add(y:Int) = x + y
  }

  def main(args: Array[String]): Unit = {
    //进行两个数的相加  1.add(2)
    println("两个数字的和是:" + 1.add(2))
  }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值