scala学习笔记
1.数据类型
数据类型 | 描述 |
Byte | 8位有符号补码整数。数值区间为 -128 到 127 |
Short | 16位有符号补码整数。数值区间为 -32768 到 32767 |
Int | 32位有符号补码整数。数值区间为 -2147483648 到 2147483647 |
Long | 64位有符号补码整数。数值区间为 -9223372036854775808 到 9223372036854775807 |
Float | 32 位, IEEE 754 标准的单精度浮点数 |
Double | 64 位 IEEE 754 标准的双精度浮点数 |
Char | 16位无符号Unicode字符, 区间值为 U+0000 到 U+FFFF |
String | 字符序列 |
Boolean | true或false |
Unit | 表示无值,和其他语言中void等同。用作不返回任何结果的方法的结果类型。Unit只有一个实例值,写成()。 |
Null | null 或空引用 |
Nothing | Nothing类型在Scala的类层级的最底端;它是任何其他类型的子类型。 |
Any | Any是所有其他类的超类 |
AnyRef | AnyRef类是Scala里所有引用类(reference class)的基类 |
1.1整型字面量
整型字面量用于 Int 类型,如果表示 Long,可以在数字后面添加 L 或者小写 l 作为后缀。
1.2浮点型字面量
如果浮点数后面有f或者F后缀时,表示这是一个Float类型,否则就是一个Double类型的。实例如下:
1.3布尔型字面量
布尔型字面量有 true 和 false。
1.4符号字面量
未明白
1.5字符字面量
在 Scala 字符变量使用单引号 ' 来定义,如下:
'a'
'\u0041'
'\n'
'\t'
其中 \ 表示转义字符,其后可以跟 u0041 数字或者 \r\n 等固定的转义字符。
1.6字符串字面量
在 Scala 字符串字面量使用双引号 " 来定义,如下:
"Hello,\nWorld!"
"菜鸟教程官网:www.runoob.com"
1.7多行字符串的表示方法
多行字符串用三个双引号来表示分隔符,格式为:""" ... """。
实例如下:
val foo = """菜鸟教程
www.runoob.com
www.w3cschool.cc
www.runnoob.com
以上三个地址都能访问"""
1.8Null
空值是 scala.Null 类型。
Scala.Null和scala.Nothing是用统一的方式处理Scala面向对象类型系统的某些"边界情况"的特殊类型。
Null类是null引用对象的类型,它是每个引用类(继承自AnyRef的类)的子类。Null不兼容值类型。
2.Scala 变量
2.1 变量声明
一、变量:在程序运行过程中其值可能发生改变的量叫做变量。如:时间,年龄。
二、常量:在程序运行过程中其值不会发生变化的量叫做常量。如:数值 3,字符'A'。
var myVar : String = "Foo"
var myVar : String = "Too"
//如果声明常量
val myVal : String = "Foo"
2.2 变量类型声明
var VariableName : DataType
2.3 变量类型引用
在 Scala 中声明变量和常量不一定要指明数据类型,在没有指明数据类型的情况下,其数据类型是通过变量或常量的初始值推断出来的。所以,如果在没有指明数据类型的情况下声明变量或常量必须要给出其初始值,否则将会报错。
var myVar = 10;
val myVal = "Hello, Scala!";
2.4 Scala 多个变量声明
val xmax, ymax = 100 // xmax, ymax都声明为100
//如果方法返回值是元组,我们可以使用 val 来声明一个元组:
3.Scala 访问修饰符
Scala 访问修饰符基本和Java的一样,分别有:private,protected,public。
如果没有指定访问修饰符,默认情况下,Scala 对象的访问级别都是 public。
Scala 中的 private 限定符,比 Java 更严格,在嵌套类情况下,外层类甚至不能访问被嵌套类的私有成员。
3.1私有(Private)成员
//用 private 关键字修饰,带有此标记的成员仅在包含了成员定义的类或对象内部可见,同样的规则还适用内部类。
class Outer{
class Inner{
private def f(){println("f")}
class InnerMost{
f() // 正确
}
}
(new Inner).f() //错误,因为f()声明为private 只有对象内部可见。
}
3.2保护(Protected)成员
//在scala 中,对保护(Protected)成员的访问比 java 更严格一些。因为它只允许保护成员在定义了该成员的的类的子类中被访问。而在java中,用protected关键字修饰的成员,除了定义了该成员的类的子类可以访问,同一个包里的其他类也可以进行访问。
package p{
class Super{
protected def f() {println("f")}
}
class Sub extends Super{
f()
}
class Other{
(new Super).f() //错误 //Other没有继承Super类,
}
}
3.3公共(Public)成员
Scala中,如果没有指定任何的修饰符,则默认为 public。这样的成员在任何地方都可以被访问。
class Outer {
class Inner {
def f() { println("f") }
class InnerMost {
f() // 正确
}
}
(new Inner).f() // 正确因为 f() 是 public
}
3.4 作用域保护
Scala中,访问修饰符可以通过使用限定词强调。格式为:
private[x] 或 protected[x]
4.Scala 运算符
运算符 | 描述 | 实例 |
+ | 加号 | A + B 运算结果为 30 |
- | 减号 | A - B 运算结果为 -10 |
| 乘号 | A B 运算结果为 200 |
/ | 除号 | B / A 运算结果为 2 |
% | 取余 | B % A 运算结果为 0 |
== | 等于 | (A == B) 运算结果为 false |
!= | 不等于 | (A != B) 运算结果为 true |
> | 大于 | (A > B) 运算结果为 false |
< | 小于 | (A < B) 运算结果为 true |
>= | 大于等于 | (A >= B) 运算结果为 false |
<= | 小于等于 | (A <= B) 运算结果为 true |
&& | 逻辑与 | (A && B) 运算结果为 false |
|| | 逻辑或 | (A || B) 运算结果为 true |
! | 逻辑非 | !(A && B) 运算结果为 true |
4.1位运算符
& | 按位与运算符 | (a & b) 输出结果 12 ,二进制解释: 0000 1100 |
| | 按位或运算符 | (a | b) 输出结果 61 ,二进制解释: 0011 1101 |
^ | 按位异或运算符 | (a ^ b) 输出结果 49 ,二进制解释: 0011 0001 |
~ | 按位取反运算符 | (~a ) 输出结果 -61 ,二进制解释: 1100 0011, 在一个有符号二进制数的补码形式。 |
<< | 左移动运算符 | a << 2 输出结果 240 ,二进制解释: 1111 0000 |
>> | 右移动运算符 | a >> 2 输出结果 15 ,二进制解释: 0000 1111 |
>>> | 无符号右移 | A >>>2 输出结果 15, 二进制解释: 0000 11112 |
4.1赋值运算符
= | 简单的赋值运算,指定右边操作数赋值给左边的操作数。 | C = A + B 将 A + B 的运算结果赋值给 C |
+= | 相加后再赋值,将左右两边的操作数相加后再赋值给左边的操作数。 | C += A 相当于 C = C + A |
-= | 相减后再赋值,将左右两边的操作数相减后再赋值给左边的操作数。 | C -= A 相当于 C = C - A |
= | 相乘后再赋值,将左右两边的操作数相乘后再赋值给左边的操作数。 | C = A 相当于 C = C * A |
/= | 相除后再赋值,将左右两边的操作数相除后再赋值给左边的操作数。 | C /= A 相当于 C = C / A |
%= | 求余后再赋值,将左右两边的操作数求余后再赋值给左边的操作数。 | C %= A is equivalent to C = C % A |
<<= | 按位左移后再赋值 | C <<= 2 相当于 C = C << 2 |
>>= | 按位右移后再赋值 | C >>= 2 相当于 C = C >> 2 |
&= | 按位与运算后赋值 | C &= 2 相当于 C = C & 2 |
^= | 按位异或运算符后再赋值 | C ^= 2 相当于 C = C ^ 2 |
|= | 按位或运算后再赋值 | C |= 2 相当于 C = C | 2 |
5.Scala IF…ELSE 语句
if(布尔表达式){
// 如果布尔表达式为 true 则执行该语句块
}else{
// 如果布尔表达式为 false 则执行该语句块
}
6.Scala 循环
while(condition)
{
statement(s);
}
do {
statement(s);
} while( condition );
//Range 可以是一个数字区间表示 i to j ,或者 i until j。左箭头 <- 用于为变量 x 赋值。
for( var x <- Range ){
statement(s);
}
//例如 to与until的区别是,to是包含10 ,until不包含10
for( a <- 1 to 10){
println( "Value of a: " + a );
}
for( a <- 1 until 10){
println( "Value of a: " + a );
}
//对于List集合进行遍历
for( var x <- List ){
statement(s);
}
//for循环与if一起使用,遍历a!=3
for( a <- numList
if a != 3; if a < 8 ){
println( "Value of a: " + a );
}
7.Scala 方法与函数
Scala 有方法与函数,二者在语义上的区别很小。Scala 方法是类的一部分,而函数是一个对象可以赋值给一个变量。换句话来说在类中定义的函数即是方法。
Scala 中的方法跟 Java 的类似,方法是组成类的一部分。
Scala 中的函数则是一个完整的对象,Scala 中的函数其实就是继承了 Trait 的类的对象。
Scala 中使用 val 语句可以定义函数,def 语句定义方法。
7.1 方法声明
def functionName ([参数列表]) : [return type]
def addInt( a:Int, b:Int ) : Int = {
var sum:Int = 0
sum = a + b
return sum
}
7.2方法调用
[instance.]functionName( 参数列表 )
Scala 也是一种函数式语言,所以函数是 Scala 语言的核心。以下一些函数概念有助于我们更好的理解 Scala 编程
1.Scala 函数传名调用(call-by-name)
Scala的解释器在解析函数参数(function arguments)时有两种方式:
传值调用(call-by-value):先计算参数表达式的值,再应用到函数内部;
传名调用(call-by-name):将未计算的参数表达式直接应用到函数内部
在进入函数内部前,传值调用方式就已经将参数表达式的值计算完毕,而传名调用是在函数内部进行参数表达式的值计算的。
这就造成了一种现象,每次使用传名调用时,解释器都会计算一次表达式的值。例子请看:https://www.runoob.com/scala/functions-call-by-name.html
def delayed( t: => Long ) = {
println("在 delayed 方法内")
println("参数: " + t)//每次使用t函数的时候就会调用t函数一次。
t//每次使用t函数的时候就会调用t函数一次。
}
2.Scala 指定函数参数名
一般情况下函数调用参数,就按照函数定义时的参数顺序一个个传递。但是我们也可以通过指定函数参数名,并且不需要按照顺序向函数传递参数,实例如下:
object Test {
def main(args: Array[String]) {
printInt(b=5, a=7); //指定b=5, a=7
}
def printInt( a:Int, b:Int ) = {
println("Value of a : " + a );
println("Value of b : " + b );
}
}
3.Scala 可变参数
Scala 允许你指明函数的最后一个参数可以是重复的,即我们不需要指定函数参数的个数,可以向函数传入可变长度参数列表。
Scala 通过在参数的类型之后放一个星号来设置可变参数(可重复的参数)。例如:
def printStrings( args:String* ) = { //args参数是可变的
var i : Int = 0;
for( arg <- args ){
println("Arg value[" + i + "] = " + arg );
i = i + 1;
}
}
4.Scala 函数 - 默认参数值
def addInt( a:Int=5, b:Int=7 ) : Int = {
var sum:Int = 0
sum = a + b
return sum
}
5.Scala 函数嵌套
我们可以在 Scala 函数内定义函数,定义在函数内的函数称之为局部函数。
以下实例我们实现阶乘运算,并使用内嵌函数:
def factorial(i: Int): Int = {
def fact(i: Int, accumulator: Int): Int = {
if (i <= 1)
accumulator
else
fact(i - 1, i * accumulator)
}
fact(i, 1)
}
6.Scala 偏应用函数
object Test {
def main(args: Array[String]) {
val date = new Date
val logWithDateBound = log(date, _ : String) //使用下划线(_)替换缺失的参数列表
logWithDateBound("message1" )
Thread.sleep(1000)
logWithDateBound("message2" )
Thread.sleep(1000)
logWithDateBound("message3" )
}
def log(date: Date, message: String) = {
println(date + "----" + message)
}
}
7.Scala 高阶函数
//高阶函数(Higher-Order Function)就是操作其他函数的函数。
//Scala 中允许使用高阶函数, 高阶函数可以使用其他函数作为参数,或者使用函数作为输出结果。
//以下实例中,apply() 函数使用了另外一个函数 f 和 值 v 作为参数,而函数 f 又调用了参数 v:
// 函数 f 和 值 v 作为参数,而函数 f 又调用了参数 v
def apply(f: Int => String, v: Int) = f(v)
8.Scala 匿名函数
Scala 中定义匿名函数的语法很简单,箭头左边是参数列表,右边是函数体。
使用匿名函数后,我们的代码变得更简洁了。
下面的表达式就定义了一个接受一个Int类型输入参数的匿名函数:
var inc = (x:Int) => x+1
上述匿名函数其实是下面这种写法的简写
def add2 = new Function1[Int,Int]{
def apply(x:Int):Int = x+1;
}
8.Scala 闭包
闭包是一个函数,返回值依赖于声明在函数外部的一个或多个变量。
闭包通常来讲可以简单的认为是可以访问一个函数里面局部变量的另外一个函数。
如下面这段匿名的函数:
def main(args: Array[String]) {
println( "muliplier(1) value = " + multiplier(1) )
println( "muliplier(2) value = " + multiplier(2) )
}
var factor = 3
val multiplier = (i:Int) => i * factor //factor作用域在函数外部,
9.Scala 数组
var myList = Array(1.9, 2.9, 3.4, 3.5)
var myList = new Array[String](3)
//创建多维数组
var myMatrix = ofDim[Int](3,3)
//合并数组
concat( myList1, myList2)
//创建区间数组
//我们使用了 range() 方法来生成一个区间范围内的数组。range() 方法最后一个参数为步长,默认为 1:
var myList1 = range(10, 20, 2)
10.Scala Collection
// 定义整型 List
val x = List(1,2,3,4)
// 定义 Set
val x = Set(1,3,5,7)
// 定义 Map
val x = Map("one" -> 1, "two" -> 2, "three" -> 3)
// 创建两个不同类型元素的元组
val x = (10, "Runoob")
// 定义 Option
val x:Option[Int] = Some(5)
10.1 Scala List(列表)
1.列表基本操作
head 返回列表第一个元素
tail 返回一个列表,包含除了第一元素之外的其他元素
isEmpty 在列表为空时返回true
2.连接列表
// 使用 ::: 运算符
var fruit = site1 ::: site2
println( "site1 ::: site2 : " + fruit )
// 使用 List.:::() 方法
fruit = site1.:::(site2)
println( "site1.:::(site2) : " + fruit )
// 使用 concat 方法
fruit = List.concat(site1, site2)
println( "List.concat(site1, site2) : " + fruit )
3.列表初始化
val site1 = "Runoob" :: ("Google" :: ("Baidu" :: Nil))
val site: List[String] = List("Runoob", "Google", "Baidu")
以上形式都可以
4.List.fill()
我们可以使用 List.fill() 方法来创建一个指定重复数量的元素列表
val num = List.fill(10)(2) // 重复元素 2, 10 次
输出:num : List(2, 2, 2, 2, 2, 2, 2, 2, 2, 2)
5.List.tabulate() 通过给定的函数来创建列表
val squares = List.tabulate(6)(n => n * n)
输出:List(0, 1, 4, 9, 16, 25)
10.2 Scala Set(集合)
默认情况下,Scala 使用的是不可变集合,如果你想使用可变集合,需要引用 scala.collection.mutable.Set 包。
1.集合基本操作
head 返回集合第一个元素
tail 返回一个集合,包含除了第一元素之外的其他元素
isEmpty 在集合为空时返回true
2.连接集合
var site = site1 ++ site2
var site = site1.++(site2)
3.交集 使用.&()函数
num1.&(num2)
10.3 Scala Map
默认情况下 Scala 使用不可变 Map。如果你需要使用可变集合,你需要显式的引入 import scala.collection.mutable.Map 类
1.Map 基本操作
keys 返回 Map 所有的键(key)
values 返回 Map 所有的值(value)
isEmpty 在 Map 为空时返回true
2.Map 合并
var colors = colors1 ++ colors2
var colors = colors1.++(colors2)
10.4 Scala 元组
与列表一样,元组也是不可变的,但与列表不同的是元组可以包含不同类型的元素。
目前 Scala 支持的元组最大长度为 22。对于更大长度你可以使用集合,或者扩展元组
元组的值是通过将单个的值包含在圆括号中构成的。例如:
val t = (1, 3.14, "Fred")
此外我们也可以使用以下方式来定义
val t = new Tuple3(1, 3.14, "Fred")
1.获取元组
val t = (4,3,2,1)
val sum = t._1 + t._2 + t._3 + t._4
getOrElse():方法获取元组中存在的元素或者使用其默认的值
2.迭代元组
Tuple.productIterator()
比如:t.productIterator().foreach(i=>println("Value = " + i ))
3.元素交换
t.swap
10. 5 Scala Option(选项)
Scala Option(选项)类型用来表示一个值是可选的(有值或无值)。
Option[T] 是一个类型为 T 的可选值的容器: 如果值存在, Option[T] 就是一个 Some[T] ,如果不存在, Option[T] 就是对象 None 。
11 Scala 类和对象
类是对象的抽象,而对象是类的具体实例。类是抽象的,不占用内存,而对象是具体的,占用存储空间。类是用于创建对象的蓝图,它是一个定义包括在特定类型的对象中的方法和变量的软件模板。
在 Scala 中,是没有 static 这个东西的,但是它也为我们提供了单例模式的实现方法,那就是使用关键字 object。
当单例对象与某个类共享同一个名称时,他被称作是这个类的伴生对象:companion object。你必须在同一个源文件里定义类和它的伴生对象。类被称为是这个单例对象的伴生类:companion class。类和它的伴生对象可以互相访问其私有成员。
伴生对象:与类名字相同,可以访问类的私有属性和方法 object xxx{}
12 Scala Trait(特征)
Scala Trait(特征) 相当于 Java 的接口,实际上它比接口还功能强大。
与接口不同的是,它还可以定义属性和方法的实现。
1.特征构造顺序(与java相同)
调用超类的构造器;
特征构造器在超类构造器之后、类构造器之前执行;
特征由左到右被构造;
每个特征当中,父特征先被构造;
如果多个特征共有一个父特征,父特征不会被重复构造
所有特征被构造完毕,子类被构造。
13 Scala 模式匹配
相当于switch
def matchTest(x: Int): String = x match {
case 1 => "one"
case 2 => "two"
case _ => "many" //default
}
//样例类:使用了case关键字的类定义就是就是样例类(case classes),样例类是种特殊的类,经过优化以用于模式匹配
object Test {
def main(args: Array[String]) {
val alice = new Person("Alice", 25)
val bob = new Person("Bob", 32)
val charlie = new Person("Charlie", 32)
for (person <- List(alice, bob, charlie)) {
person match {
case Person("Alice", 25) => println("Hi Alice!")
case Person("Bob", 32) => println("Hi Bob!")
case Person(name, age) =>
println("Age: " + age + " year, name: " + name + "?")
}
}
}
// 样例类
case class Person(name: String, age: Int)
}
在声明样例类时,下面的过程自动发生了:
构造器的每个参数都成为val,除非显式被声明为var,但是并不推荐这么做;
在伴生对象中提供了apply方法,所以可以不使用new关键字就可构建对象;
提供unapply方法使模式匹配可以工作;
生成toString、equals、hashCode和copy方法,除非显示给出这些方法的定义。
还没有评论,来说两句吧...