@

目录

Scala的基本使用

一、基础语法

1.1 变量

1.1.1 var和val

Scala中的变量分为两种:

可变var:可以随时修改var声明的变量的值

不可变val:val声明的变量,值不能被修改,否则会报错:error: reassignment to val

scala> var a = 1
a: Int = 1
scala> a = 2
a: Int = 2
scala> val b = 1
b: Int = 1
scala> b = 2
<console>:8: error: reassignment to val
b = 2
^

1.1.2 自动类型推断

无论声明val变量,还是声明var变量,都可以手动指定变量的类型;如果不指定,Scala会自动根据值,进行类型推断

scala> val c = 1
c: Int = 1 scala> val c: Int = 1
c: Int = 1

1.2 数据类型

1.2.1 基础数据类型

Byte、Char、Short、Int、Long、Float、Double、Boolean

1.2.2 增强数据类型

StringOps、RichInt、RichDouble、RichChar

增强版数据类给基本数据类型增加了上百种增强的功能

1.3 操作符

Scala的算术操作符与Java的算术操作符没有什么区别

比如+、-、*、/、%等,以及&、|、^、>>、<<等

注意: Scala中没有提供++、—–操作符

我们只能使用+和-,比如count = 1,count++是错误的,必须写做count += 1

二、流程控制

2.1 if表达式

在Scala中, IF表达式是由返回值的,就是if或者else中最后一行语句返回的值

2.2 语句终结符

Scala默认不需要语句终结符,它将每一行作为一个语句

如果一行要放多条语句,则前面的语句必须使用语句终结符

语句终结符和Java中的一样,就是我们平时使用的分号

scala> val age = 20; if(age > 18) 1 else 0
age: Int = 20
res0: Int = 1

2.3 循环

2.3.1 for循环

for循环本身的特性就没什么好说的了,直接上案例

scala> :paste
// Entering paste mode (ctrl-D to finish) val n = 10
for(i <- 1 to n)
println(i) // Exiting paste mode, now interpreting. 1
2
3
4
5
6
7
8
9
10
n: Int = 10

2.3.2 这里面的to可以换成until

scala> :paste
// Entering paste mode (ctrl-D to finish) val n = 10
for(i <- 1 until 10)
println(i) // Exiting paste mode, now interpreting. 1
2
3
4
5
6
7
8
9
n: Int = 10

to 和 until 其实都是函数,一个是闭区间,一个是开区间

2.3.3 for循环针对字符串还可以用

scala> for(c <- "hello scala") println(c)
h
e
l
l
o s
c
a
l
a
2.3.4 注意花括号

我在for循环后面没有使用花括号,都省略了,主要是因为for循环的循环体代码就只有一行,如果有多行,就需要使用花括号了,否则,最终执行的结果就不是我们想要的

没有使用{}

scala> :paste
// Entering paste mode (ctrl-D to finish) for(i <- 1 to 5)
println(i)
println("hehe") // Exiting paste mode, now interpreting. 1
2
3
4
5
hehe

使用{}

scala> :paste
// Entering paste mode (ctrl-D to finish) for(i <- 1 to 5)
{
println(i)
println("hehe")
} // Exiting paste mode, now interpreting. 1
hehe
2
hehe
3
hehe
4
hehe
5
hehe

2.3.5 while循环

它的用法和java中的while也是很像的,主要看一下语法层面的区别

scala> :paste
// Entering paste mode (ctrl-D to finish) var n = 10
while(n>0){
println(n)
n -= 1
} // Exiting paste mode, now interpreting. 10
9
8
7
6
5
4
3
2
1
n: Int = 0

2.4 高级for循环

2.4.1 if守卫模式

if守卫模式,假设我们想要获取1~10之间的所有偶数,使用普通的for循环,需要把每一个数字都循环出来,然后判断是否是偶数

如果在for循环里面使用if守卫,可以在循环的时候就执行一定的逻辑,判断数值是否是偶数

scala> for(i <- 1 to 10 if i % 2 == 0) println(i)
2
4
6
8
10

2.4.2 for推导式

for推导式,一个典型例子是构造集合

我们在使用for循环迭代数字的时候,可以使用yield指定一个规则,对迭代出来的数字进行处理,并且创建一个新的集合

scala> for(i <- 1 to 10) yield i *2
res16: scala.collection.immutable.IndexedSeq[Int] = Vector(2, 4, 6, 8, 10, 12, 14, 16, 18, 20)

三、Scala的集合体系

3.1 集合体系

3.2 集合分类

Scala中的集合是分成可变和不可变两类集合的

  • 其中可变集合就是说,集合的元素可以动态修改
  • 而不可变集合就是说,集合的元素在初始化之后,就无法修改了

    可变集合:在scala.collection.mutable这个包下面

    不可变集合:在scala.collection.immutable这个包下面

我们在创建集合的时候,如果不指定具体的包名,默认会使用不可变集合

3.3Set集合

Set代表一个没有重复元素的集合

Set集合分为可变的和不可变的集合,默认情况下使用的是不可变集合

3.3.1创建集合

不可变集合
scala> val s = Set(1,2,3)
s: scala.collection.immutable.Set[Int] = Set(1, 2, 3)
可变集合
scala> val s = scala.collection.mutable.Set(1,2,3)
s: scala.collection.mutable.Set[Int] = Set(1, 2, 3) scala> s += 4
res34: s.type = Set(1, 2, 3, 4)

3.3.2 HashSet

HashSet集合分为 可变和不可变集合

scala> val s = new scala.collection.mutable.HashSet[Int]()
s: scala.collection.mutable.HashSet[Int] = Set() scala> s +=1
res35: s.type = Set(1) scala> s +=2
res36: s.type = Set(1, 2) scala> s +=5
res38: s.type = Set(1, 5, 2)

3.3.3LinkedHashSet

LinkedHashSet 只有可变的,没有不可变的

scala> val s = new scala.collection.mutable.LinkedHashSet[Int]()
s: scala.collection.mutable.LinkedHashSet[Int] = Set() scala> s +=1
res42: s.type = Set(1) scala> s +=2
res43: s.type = Set(1, 2) scala> s +=5
res44: s.type = Set(1, 2, 5)

3.3.4 SortedSet

SortedSet分为 可变和不可变集合

SortedSet集合中的元素是按照元素的字典顺序排序的

scala> val s = scala.collection.mutable.SortedSet[String]()
s: scala.collection.mutable.SortedSet[String] = TreeSet() scala> s +=("c")
res45: s.type = TreeSet(c) scala> s +=("a")
res46: s.type = TreeSet(a, c) scala> s +=("b")
res47: s.type = TreeSet(a, b, c)

3.4 List集合

List代表一个不可变的列表

3.4.1 创建

scala>  val l = List(1, 2, 3, 4)
l: List[Int] = List(1, 2, 3, 4)

3.4.2 获取数组元素

head:表示获取List中的第一个元素

tail:表示获取List中第一个元素之后的所有元素

那其实head和tail就可以获取list中的所有元素了

scala> l.head
res49: Int = 1 scala> l.tail
res51: List[Int] = List(2, 3, 4)

通过::操作符,可以将head和tail的结果合并成一个List

scala> l.head :: l.tail
res52: List[Int] = List(1, 2, 3, 4)

3.5 ListBuffer

3.5.1 动态增加或者移除元素

scala> val lb = scala.collection.mutable.ListBuffer[Int]()
lb: scala.collection.mutable.ListBuffer[Int] = ListBuffer() scala> lb +=1
res56: lb.type = ListBuffer(1) scala> lb +=2
res57: lb.type = ListBuffer(1, 2) scala> lb +=5
res58: lb.type = ListBuffer(1, 2, 5) scala> lb -=5
res59: lb.type = ListBuffer(1, 2)

3.5.2 遍历ListBuffer

scala> for(i <- lb) println(i)
1
2

3.6 Map集合

Map是一种可迭代的键值对(key/value)结构

Map分为可变和不可变,默认情况下使用的是不可变Map

3.6.1创建Map

创建一个不可变的Map
scala> val ages = Map("jack"->30,"tom"->25,"jessic"->23)
ages: scala.collection.immutable.Map[String,Int] = Map(jack -> 30, tom -> 25, jessic -> 23) scala> ages("jack")
res100: Int = 30
创建一个可变的Map
scala> val ages = scala.collection.mutable.Map("jack"->30,"tom"->25,"jessic"->23)
ages: scala.collection.mutable.Map[String,Int] = Map(jessic -> 23, jack -> 30, tom -> 25) scala> ages("jack")
res101: Int = 30
还有一种创建Map的简易方式,这种方式创建的是不可变Map
scala> val ages = Map(("jack",30),("tom",25),("jessic"->23))
ages: scala.collection.immutable.Map[String,Int] = Map(jack -> 30, tom -> 25, jessic -> 23)

3.6.2 查询

一般查询
scala> val ages = scala.collection.mutable.Map(("jack",30),("tom",25),("jessic"->23))
ages: scala.collection.mutable.Map[String,Int] = Map(jessic -> 23, jack -> 30, tom -> 25) scala> val age = ages("jack")
age: Int = 30 scala> val age = ages("jack1")
java.util.NoSuchElementException: key not found: jack1
key不存在处理

获取指定key对应的value,如果key不存在,会报错

使用if-else语句,如果指定的key不存在,则返回一个默认值

scala> val age = if (ages.contains("jack1")) ages("jack1") else 0
age: Int = 0
getOrElse函数

map中还有一个getOrElse函数

建议后期从map中获取数据都使用这个getOrElse函数

scala> val age = ages.getOrElse("jack1", 0)
age: Int = 0 scala> val age = ages.getOrElse("jack", 0)
age: Int = 30

3.6.3 修改

更新map中的元素
scala> ages("jack") = 31

scala> ages
res104: scala.collection.mutable.Map[String,Int] = Map(jessic -> 23, jack -> 31, tom -> 25)
增加多个元素
scala> ages += ("hehe" -> 35, "haha" -> 40)
res105: ages.type = Map(hehe -> 35, jessic -> 23, jack -> 31, tom -> 25, haha -> 40)
移除元素
scala> ages -= "hehe"
res106: ages.type = Map(jessic -> 23, jack -> 31, tom -> 25, haha -> 40)

3.6.4 遍历

遍历map的entrySet
scala> for ((key, value) <- ages) println(key + " " + value)
jessic 23
jack 31
tom 25
haha 40
遍历map的key
scala> for (key <- ages.keySet) println(key)
jessic
jack
tom
haha
遍历map的value
scala> for (value <- ages.values) println(value)
23
31
25
40

3.6.5 最后看一下Map的几个子类

HashMap、SortedMap和LinkedHashMap

HashMap:是一个按照key的hash值进行排列存储的map

SortedMap:可以自动对Map中的key进行排序【有序的map】

LinkedHashMap:可以记住插入的key-value的顺序

HashMap分为可变和不可变的,没有什么特殊之处

在这主要演示一下SortedMap和LinkedHashMap

SortedMap是不可变的

scala> val ages = scala.collection.immutable.SortedMap("b" -> 30, "a" -> 15, "c" -> 25)
ages: scala.collection.immutable.SortedMap[String,Int] = Map(a -> 15, b -> 30, c -> 25) scala> ages
res112: scala.collection.immutable.SortedMap[String,Int] = Map(a -> 15, b -> 30, c -> 25)

LinkedHashMap是可变的

scala> val ages = new scala.collection.mutable.LinkedHashMap[String, Int]()
ages: scala.collection.mutable.LinkedHashMap[String,Int] = Map() scala> ages("b")=30 scala> ages("a")=15 scala> ages("c")=25 scala> ages
res116: scala.collection.mutable.LinkedHashMap[String,Int] = Map(b -> 30, a -> 15, c -> 25)

3.7 Array

Scala中Array的含义与Java中的数组类似,长度不可变,数组初始化后,长度就固定下来了,而且元素全部根据其类型进行初始化,可以直接使用Array()创建数组,元素类型自动推断

3.8 ArrayBuffer

Scala中ArrayBuffer与Java中的ArrayList类似,长度可变

ArrayBuffer:支持添加元素、移除元素

如果不想每次都使用全限定名,则可以预先导入ArrayBuffer类

scala> import scala.collection.mutable.ArrayBuffer
import scala.collection.mutable.ArrayBuffer

3.8.1 初始化

使用ArrayBuffer()的方式可以创建一个空的ArrayBuffer

scala> val b = new ArrayBuffer[Int]()
b: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer()

3.8.2 添加元素

使用+=操作符,可以添加一个元素,或者多个元素

b += 1 或者 b += (2, 3, 4, 5)

scala> b += 1
res69: b.type = ArrayBuffer(1) scala> b += (2, 3, 4, 5)
res70: b.type = ArrayBuffer(1, 2, 3, 4, 5)

3.8.3 指定位置插入元素

使用insert()函数可以在指定位置插入元素,但是这种操作效率很低,因为需要移动指定位置后的所有元素

向3号角标的位置添加一个元素 30

scala> b.insert(3,30)

scala> b
res72: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3, 30, 4, 5)

3.8.4 移除元素

使用remove()函数可以移除指定位置的元素

移除1号角标的元素

scala> b.remove(1)
res73: Int = 2 scala> b
res74: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 3, 30, 4, 5)

3.8.5 Array与ArrayBuffer的转换

Array与ArrayBuffer可以互相进行转换

b.toArray:ArrayBuffer转Array

a.toBuffer:Array转ArrayBuffer

3.9 数组常见操作

3.9.1 遍历

scala> val b=ArrayBuffer(1, 2, 3, 4, 5)
b: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3, 4, 5) scala> for(i <- b) println(i)
1
2
3
4
5 scala> for(i <- 0 until b.length ) println(b(i))
1
2
3
4
5

3.9.2 求和、求最大值

scala> val a = Array(3, 2, 1, 4, 5)
a: Array[Int] = Array(3, 2, 1, 4, 5) scala> val sum = a.sum
sum: Int = 15 scala> val max = a.max

3.9.3 数组排序

scala> scala.util.Sorting.quickSort(a)

scala> a
res99: Array[Int] = Array(1, 2, 3, 4, 5)

3.10 Tuple

Tuple:称之为元组,它与Array类似,都是不可变的,但与数组不同的是元组可以包含不同类型的元素

Tuple中的元素角标从 1 开始

目前 Scala 支持的元组最大长度为 22 ,对于更大长度可以使用集合或数组

scala> val t = (1, 3.14, "hehe")
t: (Int, Double, String) = (1,3.14,hehe) scala> t._1
res117: Int = 1 scala> t._3
res118: String = hehe

3.11 总结

3.11.1 可变集合

LinkedHashSet、ListBuffer、ArrayBuffer、LinkedHashMap

3.11.2 不可变集合

List、SortedMap

3.11.3 可变+不可变集合

Set、HashSet、SortedSet、Map、HashMap

3.11.4 还有两个编外人员:

Array、Tuple

Array:长度不可变,里面的元素可变

Tuple:长度不可变,里面的元素也不可变

四、Scala中函数的使用

4.1 函数的定义

4.1.1 定义函数

在Scala中定义函数需要使用 def 关键字,函数包括函数名、参数、函数体

4.1.2 函数的返回值

Scala要求必须给出函数所有参数的类型,但是函数返回值的类型不是必须的,因为Scala可以自己根据函数体中的表达式推断出返回值类型。

4.1.3 区别

函数中最后一行代码的返回值就是整个函数的返回值,不需要使用return,这一点与Java不同,java中函数的返回值是必须要使用return的

4.1.4 单行函数

scala> def sayHello(name: String) = print("Hello, " + name)

sayHello: (name: String)Unit

scala> sayHello("Scala")

Hello, Scala

4.1.5 多行函数

scala> :paste

// Entering paste mode (ctrl-D to finish)

def sayHello(name: String, age: Int) = {

println("My name is "+name+",age is "+age)

age

}

// Exiting paste mode, now interpreting

sayHello: (name: String, age: Int)Int

scala> sayHello("Scala",18)

My name is Scala,age is 18

res120: Int = 18

4.2 函数的参数

4.2.1 默认参数

在Scala中,有时候我们调用某些函数时,不希望给出参数的具体值,而是希望使用参数自身默认的值,此时就需要在定义函数时使用默认参数。

如果给出的参数不够,则会从左往右依次应用参数。

scala> def sayHello(fName: String, mName: String = "mid", lName: String = "last") = fName + " " + mName + " " + lName
sayHello: (fName: String, mName: String, lName: String)String scala> sayHello("zhang","san")
res122: String = zhang san last
scala实现
def sayHello(name: String ="defaultName" , age: Int = 18) {
println("Hello, " + name + ", your age is " + age)
}
java实现
public void sayHello(String name, int age) {
if(name == null) {
name = "defaultName"
}
if(age == 0) {
age = 18
}
System.out.println("Hello, " + name + ", your age is " + age)
}

4.2.2 带名参数

在调用函数时,也可以不按照函数定义的参数顺序来传递参数,而是使用带名参数的方式来传递。

scala> def sayHello(fName: String, mName: String = "mid", lName: String = "last") = fName + " " + mName + " " + lName
sayHello: (fName: String, mName: String, lName: String)String scala> sayHello(fName = "Mick", lName = "Tom", mName = "Jack")
res127: String = Mick Jack Tom

4.2.3 可变参数

在Scala中,有时我们需要将函数定义为参数个数可变的形式,则此时可以使用变长参数来定义函数。

scala> :paste
// Entering paste mode (ctrl-D to finish) def sum(nums: Int*) = {
var res = 0
for (num <- nums) res += num
res
} // Exiting paste mode, now interpreting. sum: (nums: Int*)Int scala> sum(1,2,3,4,5)
res129: Int = 15

4.3 过程-特殊的函数

4.3.1 定义

定义函数时,如果函数体直接在花括号里面而没有使用=连接,则函数的返回值类型就是Unit,这样的函数称之为过程

过程通常用于不需要返回值的函数

4.3.2 写法

过程还有一种写法,就是将函数的返回值类型显式定义为Unit

比较一下这四种写法的区别

函数:

def sayHello(name: String) = "Hello, " + name
def sayHello(name: String): String = "Hello, " + name

过程:

def sayHello(name: String) {  "Hello, " + name }
def sayHello(name: String): Unit = "Hello, " + name

4.4 lazy

将一个变量声明为lazy,则只有在第一次使用该变量时,变量对应的表达式才会发生计算

4.4.1 使用场景

什么场景下需要使用lazy特性呢?

这种特性对于特别耗时的操作特别有用,比如打开文件这个操作。

scala> import scala.io.Source._
import scala.io.Source._ scala> lazy val lines = fromFile("D://test.txt").mkString
lines: String = <lazy>

即使D://test.txt文件不存在,代码也不会报错,只有变量使用时才会报错,这就是lazy这个特性。

scala> lines
java.io.FileNotFoundException: D:\test.txt (系统找不到指定的文件。)
.......

Scala的基本使用的更多相关文章

  1. jdb调试scala代码的简单介绍

    在linux调试C/C++的代码需要通过gdb,调试java代码呢?那就需要用到jdb工具了.关于jdb的用法在网上大家都可以找到相应的文章,但是对scala进行调试的就比较少了.其实调试的大致流程都 ...

  2. scala练习题1 基础知识

    1, 在scala REPL中输入3. 然后按下tab键,有哪些方法可以被调用? 24个方法可以被调用, 8个基本类型: 基本的操作符, 等:     2,在scala REPL中,计算3的平方根,然 ...

  3. 牛顿法求平方根 scala

    你任说1个整数x,我任猜它的平方根为y,如果不对或精度不够准确,那我令y = (y+x/y)/2.如此循环反复下去,y就会无限逼近x的平方根.scala代码牛顿智商太高了println( sqr(10 ...

  4. Scala集合和Java集合对应转换关系

    作者:Syn良子 出处:http://www.cnblogs.com/cssdongl 转载请注明出处 用Scala编码的时候,经常会遇到scala集合和Java集合互相转换的case,特意mark一 ...

  5. Scala化规则引擎

    1. 引言 什么是规则引擎 一个业务规则包含一组条件和在此条件下执行的操作,它们表示业务规则应用程序的一段业务逻辑.业务规则通常应该由业务分析人员和策略管理者开发和修改,但有些复杂的业务规则也可以由技 ...

  6. Scala快速概览

    IDEA工具安装及scala基本操作 目录 一. 1. 2. 3. 4. 二. 1. 2. 3. 三. 1. 2. 3. 4. 5. 6. 7. 四. 1. (1) (2) (3) (4) (5) ( ...

  7. Scala Macros - scalamela 1.x,inline-meta annotations

    在上期讨论中我们介绍了Scala Macros,它可以说是工具库编程人员不可或缺的编程手段,可以实现编译器在编译源代码时对源代码进行的修改.扩展和替换,如此可以对用户屏蔽工具库复杂的内部细节,使他们可 ...

  8. Scala Macros - 元编程 Metaprogramming with Def Macros

    Scala Macros对scala函数库编程人员来说是一项不可或缺的编程工具,可以通过它来解决一些用普通编程或者类层次编程(type level programming)都无法解决的问题,这是因为S ...

  9. Scala Reflection - Mirrors,ClassTag,TypeTag and WeakTypeTag

    反射reflection是程序对自身的检查.验证甚至代码修改功能.反射可以通过它的Reify功能来实时自动构建生成静态的Scala实例如:类(class).方法(method).表达式(express ...

  10. Scala For Java的一些参考

          变量 String yourPast = "Good Java Programmer"; val yourPast : String = "Good Java ...

随机推荐

  1. 2020-01-25:redis中,哨兵如何选举?

    福哥答案2020-01-25: [答案1:](https://bbs.csdn.net/topics/398982967)redis-sentinel故障转移的流程:1.当多个sentinel发现并确 ...

  2. 2021-02-27:假设一个固定大小为W的窗口,依次划过arr,返回每一次滑出状况的最大值。例如,arr = [4,3,5,4,3,3,6,7], W = 3。返回:[5,5,5,4,6,7]。

    2021-02-27:假设一个固定大小为W的窗口,依次划过arr,返回每一次滑出状况的最大值.例如,arr = [4,3,5,4,3,3,6,7], W = 3.返回:[5,5,5,4,6,7]. 福 ...

  3. 【Java】水果超市管理系统

    前言 说是个系统,看着像实训的产物,但实际上这是Java课程最后一个关于jdbc的大实验,yes,挺大的. 过程 看着视频里的一堆一堆的文件,逻辑混乱的讲解,我决定 我自己写这个系统 说干就干: 分析 ...

  4. MD5加密后为0e开头的字符串

    QNKCDZO         0e830400451993494058024219903391 s878926199a      0e545993274517709034328855841020 s ...

  5. How to fix the problem that Raspberry Pi cannot use the root user for SSH login All In One

    How to fix the problem that Raspberry Pi cannot use the root user for SSH login All In One 如何修复树莓派无法 ...

  6. jQuery 添加水印

    jQuery 添加水印 <script src="../../../../AJs/jquery.min.js"></script> <script t ...

  7. 预测 motif 的计算原理

    本文章来源于简书,作者小潤澤,已获原作者授权:部分内容有调整. 前言 蛋白质中功能的基本单元是 domain,是一种特殊的三维结构,不同结构的 domain 与其他分子特异性结合从而发挥功能.与此类似 ...

  8. C# .NET CORE .NET6 RSA 公钥加密 私钥解密

    环境说明: .NET CORE 版本:.NET 6 . .NET CORE 对于RSA的支持: 1. .NET 6 中内置了对 PKCS1,PKCS8 2种私钥格式的支持. 2. 如果你要部署在Lin ...

  9. 「学习笔记」DP 学习笔记1

    序列 DP 一般序列 DP 核心思想:将序列的前 \(i\) 个数的状态用一个更简单的形式表示出,并且体现出这些状态对后续的影响. 题目 ABC 267D 给定一个序列 \(a\),找到一个长度为 \ ...

  10. vscode使用chatGPT

    vscode使用chatGPT 一.下载chatPGT 在拓展中找到chatGPT,我这里下载的是中文版 二.使用 1.使用快捷键 ctrl+shift+p进行查找 chatGPT 2.点击请输入问题 ...