Scala
多范式编程语言(面向对象编程和函数式编程),开发环境需要安装scala,部署环境有java环境即可正常运行
重点:高阶函数,即函数可以作为参数传递
六大特性
- 混编
- 类型自动推断
- 适合高并发和分布式
- 特征特质trait
- 模式匹配
- 高阶函数
数据类型
- any
- anyref
- nothing
- anyval
- nothing
- anyref
- 基本数据类型同java
- unit表示空值
- nil表示长度为0的list
开发特点
-
没有类似于static的关键字,不能通过关键字修饰静态属性、方法、代码块,Object中所有内容均为静态
-
重写构造器时,要先调用默认构造器
def this(myname: String, myage: Int, mymoney: Int) { this(myname, myage); money = mymoney }
-
class和Object名字相同时互为伴生类和伴生对象,可以互相访问私有属性
-
没有自增符号 ++ --,可以使用 +=
-
to/until的使用
println(1 to 10) println(1 to (10, 2)) println(1 until(10))
-
for循环
for (i <- 1 to 10) { println(i) } for (i <- 1 to 10; if i > 5) { println(i) } for (i <- 1 to 9; j <- 1 to i) { print(i + "*" + j + "=" + i * j + " ") if (i == j) println() }
-
自动将函数的最后一行作为返回值,可以省略return
-
隐式推断:scala具有类型自动推断的特性,可以省略返回类型,如果使用return,则必须声明返回类型
函数
递归函数
def factorial(n: Int): Int = {
if (n <= 1)
1
else
n * factorial(n - 1)
}
有默认值参数的函数
def main(args: Array[String]) {
println( "Returned Value : " + addInt() );
}
def addInt( a:Int = 5, b:Int = 7 ) : Int = {
var sum:Int = 0
sum = a + b
return sum
}
可变参数函数
def main(args: Array[String]) {
printStrings("Hello", "Scala", "Python");
}
def printStrings( args:String* ) = {
var i : Int = 0;
for( arg <- args ){
println("Arg value[" + i + "] = " + arg );
i = i + 1;
}
}
偏应用函数
/**
* 偏函数
* 一个函数中只有case,没有match
* 偏函数不一定会对所有元素进行操作,只会对偏函数感兴趣的元素去操作
* 偏函数写法:没有参数,最重要的在于isDefinedAt和apply
*
* 举例:map和collect的区别
*/
def myTest:PartialFunction[String, String] = {
//[String,String]第一个为入参类型,第二个为返回值类型
case "scala" => {"scala"}
case "hello" => {"hello"}
case _ => {"no match"}
}
柯里化函数
def fun5(a:Int, b:Int)(c:Int, d:Int) = {
a + b + c + d
}
println(fun5(1, 2)(3, 4))
匿名函数
//箭头左边是参数列表
//箭头右边是函数体
() => {}
var anon = (a:Int, b:Int) => {a+b}
高阶函数
//函数的参数是函数
//主函数(fun1)的其中一个参数,是一个规定了参数个数、参数类型、返回值类型的次函数(f)
//次函数(f)具体方法名可以在调用主函数(fun1)的时候通过传参(sum)进行确定
//次函数也可以为匿名函数,在主函数传参的时候进行定义
def fun1(a:Int, f:(Int, Int) => Int) = {
var result = f(4, 4)
println("------------")
a * result
}
def sum(a:Int, b:Int) = {
a + b
}
print(fun1(5, sum))
//传参为匿名函数
print(fun1(5, (a:Int, b:Int) => {a - b}))
//函数的返回值是函数
//返回值是一个规定了参数数量、参数类型、返回值类型的函数
def fun2(a:String, b:String) : (String, String) => String = {
def fun3(c:String, d:String) = {
a + b + c + d
}
fun3
}
val result: (String, String) => String = fun2("1", "2")
println(result("3", "4"))
println(fun2("1", "2")("3", "4"))
//参数和返回值均为函数
def fun4(f:(Int, Int) => Int) : (Int, Int) => Int = {
f
}
println(fun4((a:Int, b:Int) => {a + b})(1, 2))
println(fun4(_+_)(3, 4))
开发方法
数组
/**
* 数组创建、遍历、方法举例
*/
val array: Array[Int] = Array(1, 2, 3)
for (i <- array) {
println(i)
}
//foreach操作的是array中的每一个元素,参数传入匿名函数
array.foreach(i => println(i))
//多维数组
val arr4 = Array[Array[Int]](Array(1,2), Array(3,4))
arr4.foreach(i => {
i.foreach(j => {
println(j)
})
})
for (arr <- arr4; i <- arr) {
println(i)
}
val arr1 = Array(1,2)
val arr2 = Array(3,4)
val array = Array.concat(arr1, arr2)
array.foreach(println)
val strings: Array[String] = Array.fill(5)("nihao")
/**
* 可变长度数组
*/
val array = ArrayBuffer[String]("a", "b", "c")
array.append("e", "f")
array.+= ("1")//追加在数组尾
array.+=: ("2")//带: 追加在数组头部
array.foreach(println)
List
/**
* List创建及方法举例
*/
val list = List(1, 2, 3)
list.foreach(println)
for (i <- list) {
println(i)
}
//过滤元素
val result: List[Int] = list.filter(i => {
if (i > 2) {
true
} else {
false
}
})
result.foreach(println)
//计算符合条件的元素个数
println(list.count(i =>true))
/**
* 可变长度List
*/
val listBuffer = ListBuffer(1, 2, 3)
listBuffer.append(4)
listBuffer.+=:(0)
listBuffer.+=(5)
listBuffer.foreach(println)
Map
/**
* map & flatmap
* map:映射,将一个东西变成另一个东西,一进一出
* flatmap:map + flat 业务逻辑处理+数据压平,支持一对多
*/
val list1: List[String] = list.map(i => i + "10")
list1.foreach(println)
val list2 = List("hello beijing", "hello shanghai", "hello guangzhou")
val stringses: List[Array[String]] = list2.map(line => line.split(" "))
stringses.foreach(i => {
i.foreach(println)
})
val strings: List[String] = list2.flatMap(i => {
i.split(" ")
})
strings.foreach(println)
val map = Map(
"name" -> "zs",
"sex" -> "man"
)
map.foreach(x => {
x._1 + ":" + x._2
})
//scala推荐使用option对象来作为有可能返回空的函数的值得返回类型,option中包含两个对象(Some, None)
val option: Option[String] = map.get("name")
val option1: Option[String] = map.get("name2")
println(option)
println(option1)
println(option1.getOrElse("none"))
//一步单位
println(map.getOrElse("name", "none"))
/**
* 遍历手段
*/
val keys: Iterable[String] = map.keys
keys.foreach(println)
keys.foreach(i => {
println(map.get(i).get)
})
val set: Set[String] = map.keySet
set.foreach(println)
set.foreach(i => {
println(map.get(i).get)
})
val values: Iterable[String] = map.values
values.foreach(println)
val map1 = Map(
"name" -> "ls",
"sex" -> "women"
)
val map2: Map[String, String] = map.++(map1)//以第一个为主map
val map3: Map[String, String] = map.++:(map1)//以第二个为主map
map2.foreach(println)
map3.foreach(println)
val map4 = Map(
"one" -> 15,
"two" -> 20,
"three" -> 25
)
val filterresult = map4.filter(x => {
if (x._2 >= 20) {
true
} else {
false
}
})
filterresult.foreach(println)
val countResult: Int = map4.count(x => {
if (x._2 > 20) {
true
} else {
false
}
})
println(countResult)
val bool = map4.contains("one")
println(bool)
if (map4.contains("two")) {
println(map.get("two"))
}
val bool1 = map4.exists(x => {
if (x._2 > 20) {
//exists会在找到符合逻辑的数据之后就停止遍历
true
} else {
false
}
})
println(bool1)
/**
* 可变Map
* scala.collection.mutable.Map
*/
val map: mutable.Map[String, Any] = Map(("name", "pzl"), ("age", 24))
//如果想要添加原来map中没有的value类型,要手动修改类型为[String, Any]
map+=(("money",1),("height",170))
map+=("weight" -> 140)
map-=("age")
map.foreach(println)
Set
val set1 = Set(1, 2, 3)
val set2 = Set(4, 5, 6)
//求并集
val set = set1.union(set2)
//求差集
val set3 = set1.diff(set2)
//求交集
val set4 = set1.intersect(set2)
val set5 = set1 & set2//交集
val set6 = set1 &~ set2//差集
val max = set.max
val list: List[Int] = set.toList
val str: String = set.mkString("$")
println(str)
/**
* 可变set
*/
val set7 = mutable.Set(1, 2, 3)
//因为无序,所以set的追加方法不是append,是add
set7.add(4);
set7.+=(5,6,7,8)
Tuple元组
val tuple: (Int, Int) = new Tuple2(1, 2)
val tuple1: (Int, Int, Int) = Tuple3(1, 2, 3)
//创建二元组的特殊方式
val tuple2: (String, String) = "name" -> "zs"
val tuple4: (String, Int) = ("age", 18)
val tuple3: (Int, String, Float, Long) = Tuple4(1, "2", 3.0f, 4L)
/**
* 遍历
* 获取迭代器
* 因为tuple元组本质上不是集合,但是在遍历的时候可以当做一个集合使用(迭代器)
*/
val productIterator: Iterator[Any] = tuple3.productIterator
while (productIterator.hasNext) {
println(productIterator.next())
}
/**
* 二元组的特殊方法
*/
val swap = tuple.swap
val productIterator: Iterator[Any] = swap.productIterator
while (productIterator.hasNext) {
println(productIterator.next())
}
println(swap.toString())
Trait(特征)
类似于Java中的接口,可以定义属性和实现方法,并且可以多继承
trait Play {
val name = "zs"
def play() = {
println("I'm playing")
}
}
trait Study {
val name = "ls"
def study() = {
println("I'm learning")
}
}
class People extends Play with Study {
//当继承的类中有重复的属性值时,需要重写属性
override val name: String = "pzl"
}
object Test_Trait {
def main(args: Array[String]): Unit = {
val people = new People
people.play()
people.study()
}
}
Match
def main(args: Array[String]): Unit = {
val tuple: (Int, String, Float, Char) = (1, "2", 3.0f, 'd')
val iterator = tuple.productIterator
while(iterator.hasNext) {
test_Match(iterator.next())
}
}
def test_Match(x:Any): Unit = {
x match {
case 1 => println(1)
case "2" => println("2")
//将大类型放在后面,先看看能不能获取到更加精准的结果
case x:String => println("is String")
case _ => println("no")
}
}
Implicit
/**
* 隐式转换是在scala编译器进行类型匹配时,如果找不到合适的类型
* 那么隐式转换会让编译器在作用范围内自动推导出合适的类型
*/
/**
* 隐式值与隐式参数
* 当以隐式参数作为参数的方法被调用但没有传参的时候
* 自动将作用域范围内的隐式值作为参数(类型一致)
*/
implicit val address = "shanghai"
implicit val age = 18
def test(implicit x:String) = {
println(x)
}
def test2(implicit x:String = "beijing") = {
println(x)
}
/**
* 多参数情况下,要用柯里化函数,并且将隐式参数放在最后面
* @param x
* @param y
*/
def test3(x:String = "beijing")(implicit y:Int) = {
println(x + y)
}
def main(args: Array[String]): Unit = {
test("zs")
test
test2
test2()
test3()
test3()(24)
}
/**
* 隐式转换函数
* 当A想要调用B中的方法时
* scala会在作用域范围内寻找是否有能把A转换成B的隐式转换函数
* 如果有则可以调用B中方法
*/
class Bird (name:String) {
def fly() = {
println("flying")
}
}
class Pig (xname:String) {
val name = xname
}
object Test2_implicit {
implicit def toBird(a:Pig): Bird = {
new Bird(a.name)
}
var pig = new Pig("zs")
pig.fly()
}
/**
* 隐式类
* 必须定义在类、包对象、伴生对象中
* 构造必须只有一个参数
* 同一个类、包对象、伴生对象中不能出现同类型构造的隐式类
*/
class Rabbit(xname:String) {
val name = xname
}
object Test3_implicit {
/**
* 作为参数传递进来的类型,可以调用这个隐式类中的属性和方法
* @param rat
*/
implicit class Animal(rat:Rabbit) {
val age = 18
def eat() = {
println("eating")
}
}
def main(args: Array[String]): Unit = {
val rabbit = new Rabbit("zs")
rabbit.eat()
println(rabbit.age)
}
}
Actor
scala中的actor在2.12版本中从scala标准库中移除,想要调用actor,需要引入akka-actor包来使用