Scala 特性
- 基于 JVM:可以与 Java 混合编程,且可相互调包。
- 类型推测:不需要显式定义数据类型,\(var\) 表示变量,\(val\) 表示常量。
- 并发和分布式(Actor,类似 Java 中的多线程 Thread)。
- Trait 特性:类似于 Java 中的 interfaces 和 abstract 结合。
- 模式匹配:match case (类似 Java 中的 switch case)。
类与对象
类 Class
- 可以传参数,且要指定参数类型。有了参数后默认有了构造函数,且属性有了 \(getter、setter\) 方法。
- 类中可以直接写执行代码,不需要定义函数。因为类在 \(new\) 的时候,除了方法(不包括构造函数)不执行,其余均执行。
- 在同一个 scala 文件中,如果类名与对象名相同时,此时类叫做对象的伴生类,对象叫做类的伴生对象,他们之间可以互相访问私有变量。
对象 Object
- 相当于类的单例对象,不需要使用 \(new\) 实例化。
- 对象中的构造器会在第一次使用时会被执行。如果一个对象从未被调用,它的构造器也不会执行。
- 对象不能传参数,除非是要 \(apply\) 方法。
函数
普通函数定义
- 定义方法使用
def
关键字,格式def 方法名(参数列表:类型):返回值类型={方法体}
。 - 方法体中最后返回值可以使用
return
。如果使用return
,返回值类型一定要指定。相反,如果方法体中没有return
,则默认返回方法体中最后一行计算的结果,此时返回值类型可以省略。 - 方法体如果可以一行解决,包含方法体的
{}
可以省略。 - 如果定义方法时,方法名和方法体之间的
=
被省略了,此方法最后会返回空值unit
。
def max(a: Int, b: Int): Int ={
if(a > b){
return a
} else {
return b
}
}
def max(a: Int, b: Int) ={
if(a > b){
a
} else {
b
}
}
def max(a: Int, b: Int) = if(a > b) b else a
递归函数
- 递归方法要显式的指明返回类型
def fun(num: Int): Int ={
if(num == 1) 1 else num * fun(num - 1)
}
println(fun(5))
默认值参数的函数
def fun(a: Int = 100, b: Int = 200) = a + b
println(fun(1, 2)) // 对应位置 3
println(fun(1)) // 最后一位 201
println(fun(a = 1, b = 2)) // 指定参数 3
变长参数的函数
def fun(s:String*) ={
for(elem <- s) {
println(elem)
}
// foreach
s.foreach(elem => {println(elem)})
// 简化
s.foreach(println(_))
// 再简化
s.foreach(println)
}
fun("hello", "world", "scala")
匿名函数
- 只要出现
=>
,就是匿名函数
val stringToUnit: String => Unit = (s: String) => println(s)
stringToUnit("Hello")
嵌套函数
def outerFun(number: Int) ={
def innerFun(num: Int): Int ={
if(num == 1) 1
else num * innerFun(num - 1)
}
innerFun(number)
}
println(outerFun(5))
偏应用函数
- 某些情况下,方法参数非常多,且该方法多次调用,但是其中有些参数固定不变,则可以定义偏应用函数。
val data = new Date()
def showLog(date: Date, str: String) ={
println(s"date is $date, log is $str")
}
def fun = showLog(data, _:String)
fun("a")
fun("b")
高级函数
参数是函数
def sum(a:Int, b:Int) = a + b
def fun(f:(Int, Int) => Int, str:String): String ={
val sum = f(100, 200)
str + sum
}
println(fun(sum, "sum = "))
// 或者
println(fun((a:Int, b:Int) => a * b, "mul = "))
返回是函数
- 必须显式的写出返回函数的类型
- 如果不显式写出,需要在返回函数后面加上
_
def fun(str:String): (String, String) => String ={
def retFun(str1:String, str2:String): String = str + str1 + str2
retFun
}
println(fun("1")("2", "3"))
// 不显式的话
def fun(str:String) ={
def retFun(str1:String, str2:String): String = str + str1 + str2
retFun _
}
两者都是函数
def fun(f:(Int, Int) => Int): (String, String) => String ={
val sum = f(1, 2)
def retFun(str1:String, str2:String): String ={
str1 + str2 + sum
}
retFun
}
println(fun((a, b) => a + b)("a + ", "b = "))
柯里化函数
def fun(a: Int, b: Int)(c: Int, d: Int) = a + b + c + d
println(fun(1,2)(3,4))
字符串和集合
map() 与 flatmap()
val list = List[String]("hello scala", "hello java", "hello spark")
val result1 = list.map(s => {
s.split(" ")
})
val result2 = list.flatMap(s => {
s.split(" ")
})
result1.foreach(arr => {arr.foreach(println)})
result2.foreach(println)
数组 Array
// 不可变长数组
val arr = Array[String]("a", "b", "c")
// 定义长度为3的数组arr1
val arr1 = new Array[Int](3)
arr1(0) = 2;
// 打印
arr.foreach(elem=>println(elem))
arr.foreach(println(_))
arr1.foreach(println)
// 可变长数组
var arr2 = ArrayBuffer[Int](1, 2, 3)
// append 等同于 += ,新增元素在数组最后面
arr2.append(6)
arr2.+=(7)
// +=: 则是新增元素在数组最前面
arr2.+=:(8)
// 二维数组
val secArray = new Array[Array[String]](10)
for(index <- 0 until secArray.length){
secArray(index) = new Array[String](10)
}
列表 List
// 定长列表 list
val list = List[String]("hello world", "hello scala")
// filter方法,过滤器,匹配上了就保留,否则舍弃
val value: List[String] = list.filter(s => {
"hello world".equals(s)
})
// 可变长列表 list
var list2 = ListBuffer[Int](1, 2, 3)
// append 等同于 += ,新增元素在数组最后面
list2.append(6)
list2.+=(7)
// +=: 则是新增元素在数组最前面
list2.+=:(8)
集合 Set
// 无序,去重
val set = Set[Int](1, 2, 3, 4)
val set1 = Set[Int](3, 4, 5, 6)
// 并集
set.concat(set1).foreach(println)
// 交集
set.intersect(set1).foreach(println)
// 差集
set.diff(set1).foreach(println)
// 可变 set
import scala.collection.mutable
val set2 = mutable.Set[Int](1, 2, 3)
set2.add(5)
// 不可变 set
import scala.collection.immutable
val set3 = immutable.Set[Int](1,2,3)
// 转成数组,list
set1.toArray.foreach{println}
set1.toList.foreach{println}
集合 Map
val map = Map[String, Int]("a" -> 100, "b" -> 200, "c" -> 300, "e" -> 500)
val map2 = Map[String,Int](("a", 1),("b", 2),("c", 3),("d", 4))
map.foreach(println)
// 获取 key 为 ‘a’ 的 value
val value1: Option[Int] = map.get("a")
// 获取 map 中所有 key
val keys: Iterable[String] = map.keys
// 获取 map 中所有 value
val values: Iterable[Int] = map.values
// map2 追加到 map 中,相同 key 的 value 会被替换
map.++(map2).foreach(println)
// map 追加到 map2中
map.++:(map2).foreach(println)
// 可变长 Map
val map3 = mutable.Map[String,Int](("a", 1),("b", 2))
map3.put("c", 3)
// 过滤掉 map 中 value 小于 2
map3.filter(tem=>{
val key = tem._1
var value = tem._2
value >= 2
}).foreach(println)
元组 Tuple
()
中放入一堆元素就叫元组,元素类型可不同。- 最多支持 22 个元素。
- 元组可不
new
。 - 只有二元元组能使用
swap
。
val tuple2 = (1, 2)
// 打印元组第 2 个元素
println(tuple2._2)
// 遍历元组
val iterator: Iterator[Any] = tuple2.productIterator
iterator.foreach(println)
// 二元元组的翻转
println(tuple2.swap)
// toString 方法
println(tuple2.toString())
Trait 特性
- Trait 相当于 Java 的接口。
- Trait 可以定义属性和方法的实现,相当于 Java 中抽象类和接口的结合。
- 类可以继承多个 Trait,第一个用
extends
,后面用with
。 - 继承的多个 Trait 中如果有同名的方法和属性,必须要在类中使用
override
重新定义。 - Trait 中不可传参数。
trait IsEqual {
def isEqual(obj: Any): Boolean
def notIsEqual(obj: Any): Boolean = !isEqual(obj)
}
class Point(x: Int, y: Int) extends IsEqual{
val xPoint = x
val yPoint = y
override def isEqual(obj: Any): Boolean = {
obj.isInstanceOf[Point] && obj.asInstanceOf[Point].xPoint == this.xPoint
}
}
object TraitLearning {
def main(args: Array[String]): Unit = {
val point1 = new Point(1, 2)
val point2 = new Point(1, 3)
println(point1.isEqual(point2))
println(point1.notIsEqual(point2))
}
}
模式匹配 Match
- 类似与 Java 中的
switch case
。 - 不仅可以匹配值,还可以匹配类型(类型的匹配也必须要有变量名)。
- 模式匹配中,从上到下顺序匹配。
- 如果都不匹配,会匹配到
case _
,相当于default
。 - 模式范围小的应该在最前面。
def main(args: Array[String]): Unit = {
val tuple = (1, 1.2, "scala", true)
val iterator = tuple.productIterator
iterator.foreach(item => MatchTest(item))
}
def MatchTest(obj: Any) = {
obj match {
case 1 => println("value is 1")
case i:Int => println(s"type is int, value = $i")
case d:Double => println(s"type is double, value = $d")
case _ => println("no matching")
}
}
偏函数
- 在模式匹配中,只有
case
而没有match
,就可以将其定义为偏函数。 - 只能匹配相同类型,更接近于 Java 中的
switch case
。
object PartialFunction {
def Test: PartialFunction[String, Int] = {
case "a" => 1
case _ => 2
}
def main(args: Array[String]): Unit = {
val res = Test("a")
println(res)
}
}
样例类
- 使用关键字
case
修饰的类,就叫做样例类。 - 样例类默认实现了类构造函数的
getter
方法(构造函数的参数默认是val
),如果参数是var
类型,则实现了getter
和setter
方法。 - 样例类可以
new
也可以不new
。
case class Person(name: String, age: Int)
object CaseClass {
def main(args: Array[String]): Unit = {
val person = new Person("scala", 22)
println(person)
}
}
隐式转换
定义
在 \(Scala\) 编译器进行类型匹配时,如果找不到合适的类型,那么隐式转换会让编译器在作用范围内自动推导出来合适的类型。
隐式值与隐式参数
- 同类型的参数的隐式值在作用域中只能出现一次。
- 如果方法中有部分参数需要隐式转换,则需要使用柯里化,且隐式参数放在第二个括号中。
def sayName(implicit name: String): Unit ={
println(s"the name is $name")
}
// 部分参数需要隐式转换
def sayNameAndAge(age: Int)(implicit name: String)={
println(s"the name is $name,the age is $age")
}
def main(args: Array[String]): Unit = {
implicit val name = "scala"
sayName
sayName("spark")
sayNameAndAge(22)
sayNameAndAge(22)("spark")
}
隐式转换函数
如果类 A 调用了 fun 函数,但是类 A 中没有实现 fun 函数,而类 B 中却实现了此函数。那么编译器就会去找隐式转换函数(将类 A 转换为类 B)。
- 隐式转换函数只与函数的参数类型和返回类型有关,与函数名称无关。(即不能存在两个类型相同的隐式转换函数)。
class Animal(name: String){
def canFly()={
println(s"$name can fly")
}
}
case class Bird(name: String)
object ImplicitFun {
implicit def birdToAnimal(bird: Bird) = new Animal(bird.name)
def main(args: Array[String]): Unit = {
val bird = new Bird("scala")
bird.canFly()
}
}
隐式类
如果类 A 没有某种方法或者属性,而类 A 要去调用某种方法,此时可以通过隐式类来实现。
- 使用
implicit
定义的类,只能定义在类、包对象、伴生对象中。 - 隐式类的构造必须只有一个参数,否则无法识别。
- 同一作用域中不能出现同类型构造的隐式类。
class Bird(xname:String){
val name = xname
}
object ImplicitClass {
implicit class Animal(B:Bird){
def canFly()={
println(s"${B.name} can fly")
}
}
def main(args: Array[String]): Unit = {
val bird = new Bird("scala")
bird.canFly()
}
}
参考资料:
视频:https://www.bilibili.com/video/BV1oJ411m7z3
博客:https://blog.csdn.net/weixin_42142364/article/details/113430109
博客:https://blog.csdn.net/qq_44104303/article/details/117951267
标签:String,val,scala,Int,fun,println,快速,def From: https://www.cnblogs.com/fireonfire/p/16726279.html