一、Scala的集合
1、可变集合和不可变集合
val math = scala.collection.immutable.Map("Alice" ->80 ,"Bob" ->90 )
val chinese = scala.collection.mutable.Map("Alice" ->80 ,"Bob" ->90 )
chinese("Bob" )
if (chinese.contains("Bob" )){
chinese("Bob" )
}else {
-1
}
chinese.getOrElse("Bob1" ,-1 )
chinese("Bob" )=100
chinese += "Jerry" -> 79
chinese -= "Bob"
for (s <- chinese) println(s)
chinese.foreach(println)
2 、列表:List
import scala.collection.mutable
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)
val myList = mutable.LinkedList(1 ,2 ,3 ,4 ,5 ,6 )
var cur = myList
while (cur != Nil){
cur.elem =cur.elem * 2
cur = cur.next
}
println(myList)
3、序列 : 常用的序列: Vector、Range
//序列: 常用的序列: Vector、Range
val v = Vector(1 ,2 ,3 ,4 ,5 ,6 )
v.find( _ > 3 )
v.updated(2 ,100 )
println("第一种写法:" +Range(0 ,5 ))
println("第二种写法:" + (0 until 5 ))
println("第三种写法:" + (0 to 4 ))
('0' to '9' ) ++ ('A' to 'Z' )
1 to 5 toList
4、集(Set) : 是不重复元素的集合,默认的实现:HashSet
import scala.collection.mutable
var s1 = Set(10 ,2 ,0 ,1 )
s1 += 0
s1
s1 += 100
s1
var weeksDay = mutable.LinkedHashSet("星期一" ,"星期二" )
weeksDay + "星期五"
weeksDay.contains("星期二" )
var s2 = mutable.SortedSet(1 ,2 ,3 ,100 ,10 ,4 )
Set("星期一" ,"星期二" ) subsetOf(weeksDay)
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 diff set2
5 、模式匹配:相当于Java的 instanceof 、switch case
(*)Scala的一个强大的switch case 语句
(*)类型的检查
var ch1 = '-'
var flag = 0
ch1 match {
case '+' => flag = 1
case '-' => flag = -1
case _ => flag = 0
}
println(flag)
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("其他类型" )
}
var str3 = "Hello World"
str3(7 ) match {
case '+' =>println("这是一个加号" )
case '-' =>println("这是一个减号" )
case ch => println("这个字符是:" +ch)
}
var v4:Any = 100
v4 match {
case x:Int => println("这是一个整数" )
case s:String => println("这是一个字符串" )
case _ => println("其他类型" )
}
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
class Vehicle
case class Car (name:String) extends Vehicle
case class Bike (name:String) extends Vehicle
var aCar:Vehicle = new Car("这是汽车" )
aCar match {
case Car(name) => println("这是一辆汽车" )
case Bike(name)=> println("这是一辆自行车" )
case _ => println("其他类型" )
}
二、Scala的泛型: T ----> 重要
1 、泛型类: [T ]
class GenericClass [T ]{
private var content:T = _
def set(value:T) = {content = value}
def get():T = {content}
}
object GenericClass {
def main(args: Array[String]): Unit = {
var intGeneric = new GenericClass[Int]
intGeneric.set(123 )
println("得到的值:" + intGeneric.get())
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)
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的类型:
(1 )String 和String 的子类
(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
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] = c1
var c3:EatSomething[Sparrow] = new EatSomething[Sparrow](new Sparrow)
var c4:EatSomething[Animal] = c3
}
}
package demo2
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] = c1
}
}
6 、隐式转换函数
(*)前面:implicit def int2String (n:Int) : String = {n.toString}
7 、隐式参数
8 、隐式类
package demo3
class Fruit (name:String) {
def getFruitName():String = {name}
}
class Monkey (f:Fruit) {
def say() = {println("Monkey like " + f.getFruitName() ) }
}
object ImplicitDemo {
implicit def fruit2Monkey(f:Fruit):Monkey = {new Monkey(f)}
def main(args: Array[String]): Unit = {
var f:Fruit = new Fruit("香蕉" )
f.say()
}
}
def testParam(implicit name:String) = {println("The value is " + name)}
implicit val name:String = "这是一个隐式参数"
testParam
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
object ImplicitDemo4 {
implicit class Calc (x:Int) {
def add(y:Int) = x + y
}
def main(args: Array[String]): Unit = {
println("两个数字的和是:" + 1. add(2 ))
}
}