Scala中的集合
1、可变集合和不可变集合
可变集合
不可变集合:
- 集合从不改变,因此可以安全地共享其引用。
- 甚至是在一个多线程的应用程序当中也没问题。
集合的操作:
2、列表
- 不可变列表(List)
- 可变列表(LinkedList):scala.collection.mutable
3、序列
常用的序列有:Vector和Range
- Vector是ArrayBuffer的不可变版本,是一个带下标的序列*
- Range表示一个整数序列
4、集(Set)和集的操作
- 集Set是不重复元素的集合
- 和列表不同,集并不保留元素插入的顺序。默认以Hash集实现
示例1:创建集
示例2:集的操作
5、模式匹配
Scala有一个强大的模式匹配机制,可以应用在很多场合:
- switch语句
- 类型检查
Scala还提供了样本类(case class),对模式匹配进行了优化
模式匹配示例:
- 更好的switch
- Scala的守卫
- 模式匹配中的变量
- 类型模式
- 匹配数组和列表
object Demo1 {
def main(args: Array[String]): Unit = {
//相当于 switch case
var chi = "+"
var sign = 0 //标识符 判断chi 如果 - 赋值为 -1
chi match {
case "+" => sign = 1
case "-" => sign = -1
case _ => sign = 0 //_表示其他情况
}
println(sign)
//2、Scala的守卫:匹配某种类型的所有值。case _if
//匹配所有数字
var ch2 = '2'
var digit : Int= -1
ch2 match {
case '+' => println("这是一个加号")
case '-' => println("这是一个减号")
case _ if Character.isDigit(ch2) => digit = Character.digit(ch2,10)//10 代表10进制
case _ => println("其他")
}
println(digit)
//3、在模式匹配中 使用变量
var mystr = "Hello World"
mystr(6) match {
case '+' => println("这是一个加号")
case '-' => println("这是一个减号")
case ch => println(ch)
}
//4、 instanceOf 匹配类型
var v4 :Any = 1000
v4 match {
case x : Int => println("这是一个整数")
case s : String => println("这是一个字符串")
case _ => println("其他类型")
}
/**
* Scala中容易混淆的类型
* Any: 表示任何类型 ,相当于Java中的object
* Unit:表示没有值 相当于void
* Nothing: Noting类型是Scala类层级中最低端的类型: 任何类的子类
* Null: 是所有引用类型的子类,值 null
*
*Option:Scala中的Option表示一个值是可选的(有值或无值)
* Some:如果值存在,Option 就是 Some
* None:如果值不存在,Option 就是 None
*
* 四个N总结:Noting Null None Nil
* Noting:抛出异常
* Null:引用类型子类 null
* None:Some对立
* Nil:一个空的List
*
*/
//5、匹配数组和列表
var myArray = Array(1,2,3,5)
myArray match {
case Array(0) => println("数组中只有一个0")
case Array(x,y) => println("数组中包含两个元素")
case Array(x,y,z) => println("数组中包含三个元素")
case Array(x,_*) => println("这是数组,包含多个元素")
}
var myList = List(1,2,3)
myList match {
case List(0) => println("列表中只有一个0")
case List(x,y) => println("列表中包含两个元素,和是:" + (x+y))
case List(x,y,z) => println("列表中包含三个元素,和是:" + (x+y+z))
case List(x,_*) => println("这是数组,包含多个元素,和是:" + myList.sum)
}
}
}
/**
* Scala中容易混淆的类型
* Any: 表示任何类型 ,相当于Java中的object
* Unit:表示没有值 相当于void
* Nothing: Noting类型是Scala类层级中最低端的类型: 任何类的子类
* Null: 是所有引用类型的子类,值 null
*
*Option:Scala中的Option表示一个值是可选的(有值或无值)
* Some:如果值存在,Option 就是 Some
* None:如果值不存在,Option 就是 None
*
* 四个N总结:Noting Null None Nil
* Noting:抛出异常
* Null:引用类型子类 null
* None:Some对立
* Nil:一个空的List
*
*/
class Animal
case class Cat(name : String) extends Animal
case class Dog(name : String) extends Animal
object Demo2 {
def main(args: Array[String]): Unit = {
var a : Animal = new Cat("Cat")
a match {
case Cat(name) => println("动物" + name)
case Dog(name) => println("动物" + name)
case _ => println("其他动物")
}
}
}
6、样本类(CaseClass)
简单的来说,Scala的case class就是在普通的类定义前加case这个关键字,然后你可以对这些类来模式匹配。
case class带来的最大的好处是它们支持模式识别。
普通模式匹配:
其次,如果我们想判断一个对象是否是某个类的对象,跟Java一样可以使用isInstanceOf
下面这个好像有点问题
最后,在Scala中有一种更简单的方式来判断,就是case class
注意:需要在class前面使用case关键字。
Scala语言的高级特性
1、什么是泛型类
和Java或者C++一样,类和特质可以带类型参数。在Scala中,使用方括号来定义类型参数
测试程序:
2、什么是泛型函数
函数和方法也可以带类型参数。和泛型类一样,我们需要把类型参数放在方法名之后。
注意:这里的ClassTag是必须的,表示运行时的一些信息,比如类型。
3、Upper Bounds 与 Lower Bounds
类型的上界和下界,是用来定义类型变量的范围。它们的含义如下:
-
S <: T
这是类型上界的定义。也就是S必须是类型T的子类(或本身,自己也可以认为是自己的子类。 -
U >: T
这是类型下界的定义。也就是U必须是类型T的父类(或本身,自己也可以认为是自己的父类)。 -
一个简单的例子:
-
-
一个复杂一点的例子(上界):
-
再来看一个例子:
4、视图界定(View bounds)
它比 <: 适用的范围更广,除了所有的子类型,还允许隐式转换过去的类型。用 <% 表示。
尽量使用视图界定,来取代泛型的上界,因为适用的范围更加广泛。
- 上面写过的一个列子。这里由于T的上界是String,当我们传递100和200的时候,就会出现类型不匹配。
- 但是100和200是可以转成字符串的,所以我们可以使用视图界定让addTwoString方法接收更广泛的数据类型,即:字符串及其子类、可以转换成字符串的类型。
注意:使用的是 <%
- 但实际运行的时候,会出现错误
这是因为:Scala并没有定义如何将Int转换成String的规则,所以要使用视图界定,我们就必须创建转换的规则。
- 运行成功
5、协变和逆变
- 协变:
Scala的类或特征的范型定义中,如果在类型参数前面加入 +符号,就可以使类或特征变为协变了。
- 逆变
在类或特征的定义中,在类型参数之前加上一个 - 符号,就可定义逆变范型类和特征了。
总结一下: - Scala的协变:泛型变量的值可以是本身类型或者其子类的类型
- Scala的逆变:泛型变量的值可以是本身类型或者其父类的类型
- `class Animal
class Bird extends Animal
class Sparrow extends Bird
//定义第四个类 吃东西的类
class EatSomething+T
object Demo5 {
def main(args: Array[String]): Unit = {
//定义一个鸟吃东西的类
var c1 : EatSomething[Bird] = new EatSomething[Bird](new Bird)
//创建动物吃东西的类
//var c2 : EatSomething[Animal] = new EatSomething[Animal](new Animal)
var c2 : EatSomething[Animal] = c1
}
}
`
class Animal
class Bird extends Animal
class Sparrow extends Bird
//定义第四个类 吃东西的类
class EatSomething[-T](t:T)
object Demo6 {
def main(args: Array[String]): Unit = {
//定义一个鸟吃东西的类
var c1 : EatSomething[Bird] = new EatSomething[Bird](new Bird)
//定义麻雀吃东西的类
var c2 : EatSomething[Sparrow] = c1
// var b1:Bird = new Bird
// var b2:Sparrow = b1
}
}
6、隐式转换函数
所谓隐式转换函数指的是以implicit关键字申明的带有单个参数的函数。
- 前面讲视图界定时候的一个例子
- 再举一个例子:我们把Fruit对象转换成了Monkey对象
class Fruit(name : String) {
def getFruitName() : String = name
}
class Monkey(f : Fruit){
def say() = println("Monkey like " + f.getFruitName())
}
object Demo3{
def main(args: Array[String]): Unit = {
//定义一个水果对象
var f = new Fruit("Banana")
f.say()
/**
* 为了水果调用 say函数,我们定义一个隐式函数
*把水果 转换成 猴子
*
*/
}
implicit def FruitToMonkey(f : Fruit) : Monkey = {
new Monkey(f)
}
}
7、隐式参数
*使用implicit申明的函数参数叫做隐式参数。我们也可以使用隐式参数实现隐式的转换
8、隐式类
所谓隐式类: 就是对类增加implicit 限定的类,其作用主要是对类的功能加强!
object Demo4 {
def main(args: Array[String]): Unit = {
//执行两个数求和
println(1.add(2))
implicit class Cacl(x:Int){
def add (y:Int) : Int = x+y
}
}
}