scala小记
scala和java
1、scala是基于java开发的,以jvm为运行环境,将面向对象和函数式编程结合起来的静态编程语言。
2、scala是面对对象的语言,万物皆对象,对象的本质是对数据和行为的封装(对象/属性/行为)
3、scala是函数式的语言,万物皆函数,函数是将解决问题的一个个步骤的封装,通过调用函数来解决问题。
4、java通过javac编译器将.java源代码编译成.class字节码,然后在JVM上运行。scala通过scalac编译器将.scala源代码编译成.class字节码,然后在JVM上运行。
5、java的JDK中有大量的类库。而scala的JDK中包括Java的部分类库(因此可以使用部分java语法)、scala特有的语法和类库、对java的类库做了包装
基础语法
基础
1、var修饰变量,val修饰不可变的常量(但对象的属性值可以改变),能用常量的地方不用变量
2、变量声明时必须有初始值,变量类型确定后不能修改(强数据类型)
3、scala中没有运算符,所有运算符都是方法。调用对象方法时可以省略点.,如果函数参数只有0或1个,可以省略括号。
4、三元运算符可以通过if else实现,val res = if(emotion == "love") "together" else "break"
5、循环
for(i <- 1 to 3) // 两边闭
for(i <- 1 until 3) // 左闭右开
for(i <- 1 to 3 reverse) // 倒着来
for(x <- arr) // 遍历集合中的元素
6、scala中去掉了break和continue,是为了更好适应函数式编程,通常不直接使用break语句,但也提供了breakable块来在循环中抛出异常提前退出来模拟break的效果
import scala.util.control.Breaks._
breakable {
for() {
...
if() {
break()
}
}
}
7、闭包:如果一个函数,访问到了它的外部变量的值,那么这个函数和它所处的环境成为闭包。
8、scala完全面向对象,所以并没有静态的概念,无static关键字。通过单例对象object实现类似静态方法的功能(类名.方法名)
object Person {
val country:String = "China"
}
数据类型
1、scala中一切数据都是对象(java有基本类型,不同对象),都是Any的子类
2、两大类数值类型AnyVal和引用类型AnyRef都是对象
3、AnyVal的子类有Boolean/Byte/Short/Char/Int/Long/Float/Double/Unit/StringOps
4、数值类型默认为Int,加L则为Long。浮点类型默认为Double,加f则为Float
5、Unit表示方法没有返回值。它是一个数据类型,只有一个对象就是()。StringOps是对Java中的String增强
4、AnyRef的子类有scala collections、所有java类,其它scala类。
6、Null是一个类型,只有一个对象就是null。它是所有AnyRef的子类。null可以赋值给任意AnyRef。
7、Nothing是所有数据类型的子类,在一个函数没有明确返回值时使用,这样可以抛出返回值给任何变量或函数
8、scala仍然遵守低精度值类型向高精度值类型的隐式转换,高精度转低精度需要强转,比如5.2.toInt
字符串操作
1、数值转字符串.toString;字符串转数值.toInt或toDouble等(Double字符串无法toInt)
2、字符串比较,==更类似java中的equals比较的内容,eq比较的是对象地址
val s1 = "hello"
val s2 = new String("hello")
s1 == s2 // true
s1.eq(s2) // false
System.identityHashCode(s1) == System.identityHashCode(s2) // false,比较内存地址
2、多行字符串对齐
val s1 = """|select
|uid, reg_diff_day
|from table
|where uid = "10086"
""".stripMargin
3、字符串中使用$引用变量
val age = 18
val s1 = s"${age},${age+2}"
匿名函数和匿名子类
匿名函数就是没有名字的函数,比如(x:Int)=>{x+1}
1、参数类型可以省略,会自动推导,比如(x)=>{x+1}
2、只有一个参数时,可以省略圆括号,比如x=>{x+1}
3、函数体只有一行,大括号也可以省略,比如x=>x+1,跟labmda表达式就很像了
4、如果参数只出现一次,参数省略,后面的参数可以用_代替,比如_ + 1,或者两个入参的_ + _
匿名子类可以通过包含带有重写代码块的方式创建
new MyClass() {
override val name: String = ""
override def say(): void = {}
}
集合
1、集合分三大类:序列Seq、集合Set、映射Map
2、几乎所有集合类都提供了可变和不可变版本,分别位于scala.collection下的immutable和mutable
3、不可变集合指的是集合对象不可修改,每次修改就会返回一个新对象,类似java的string对象
4、可变集合则可以对原对象进行修改,而不会返回新的对象,类似StringBuilder对象
5、Array比较特殊,它不在mutable或immutable中而存在标准库中,其长度不可变,属于不可变范畴,但其实可以修改元素。ArrayBuffer为可变数组(mutable中)
6、List/Set/Map都是不可变的,每次新增都会返回新的集合。ListBuffer/mutable.Set/mutable.Map是可变的
val lis = List(1,2,3)
val lis2 = List(4,5,6)
val lis3 = lis ++ lis2 // 合并List
val lis4 = 0 :: lis // 头部添加,如果多个::是从右往左
val lis5 = lis2 :+ 7 //尾部添加
// 集合常用操作
lis.size
lis.foreach(println)
lis.mkString(",")
lis.contains(3)
lis.head; lis.last // 头元素和尾元素
lis.init; lis.tail // init为集合去掉最后一个元素,tail为集合去掉第一个元素
lis.reverse
lis.take(3); lis.takeRight(3)
lis.drop(3); lis.dropRight(3)
lis.sortBy(x=>x) // 排序,按属性大小
lis.sortwith((x,y)=> x<y) // 升序排序,元素间比较
union, intersect, diff // 两个集合的操作
sum, product, max, min // 数值聚合
map, filter, reduce
模式匹配
// 常量匹配
val a = 1
val b = 2
val operator = '+'
val res = operator match {
case '+' => a+b
case '-' => a-b
case _ => "illegal"
}
// 数值范围
def abs(x:Int) = x match {
case i: Int if i >= 0 => i
case j: Int if j<0 => -j
case _ => "illegal"
}
// 类型匹配
def desType(x:Any) = x match {
case i:Int => "Int"
case s:String => "String"
case m:List[_] => "List"
case c:Array[Int] => "Array[Int]"
}
// 匹配数组,匹配元组等
// ...
// 匹配对象
// val user = User("name",18)实际调用User伴生对象的apply方法,不经过new构造
// case后User(...)时,默认调用伴生对象的unapply,将user作为参数,unapply将比较二者,返回Some且所有属性一致才算匹配成功
class User(val name: String, val age: Int)
object User{
def apply(name: String, age: Int): User = new User(name, age)
def unapply(user: User): Option[(String, Int)] = {
if (user == null)
None
else
Some(user.name, user.age)
}
}
val user = User("name",18)
user match {
case User("name",18) => 1
case _ => 0
}
// 样例类自动生成了伴生对象,且自动提供了常用方法,比如apply,unapply,toString,hashCode等
// 样例类是为模式匹配优化的类,提供了默认unapply方法,因此可以直接模式匹配,不需要自己实现unapply
case class Person(name:String, age:Int)
val person = Person("name",18)
person match {
case Person("name",18) => 1
case _ => 0
}
// 变量声明
val (x,y) = (1,2)
val Array(first, second, _*) = Array(1,2,3,4,5)
// for循环
val map = Map("name"->"name", "age"->18)
for((k,v) <- map1) println(k+"->"+v)